smart-code-editor 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +155 -0
  2. package/lib/adapters/vanilla/index.d.ts +3 -0
  3. package/lib/adapters/vanilla/index.d.ts.map +1 -0
  4. package/lib/config/languages.d.ts +21 -0
  5. package/lib/config/languages.d.ts.map +1 -0
  6. package/lib/config/runnerStrategies.d.ts +12 -0
  7. package/lib/config/runnerStrategies.d.ts.map +1 -0
  8. package/lib/config/runnerStrategies_v2.d.ts +31 -0
  9. package/lib/config/runnerStrategies_v2.d.ts.map +1 -0
  10. package/lib/config/themes.d.ts +54 -0
  11. package/lib/config/themes.d.ts.map +1 -0
  12. package/lib/core/BackendRunner.d.ts +78 -0
  13. package/lib/core/BackendRunner.d.ts.map +1 -0
  14. package/lib/core/CodeRunner.d.ts +32 -0
  15. package/lib/core/CodeRunner.d.ts.map +1 -0
  16. package/lib/core/LanguageManager.d.ts +41 -0
  17. package/lib/core/LanguageManager.d.ts.map +1 -0
  18. package/lib/core/LayoutManager.d.ts +59 -0
  19. package/lib/core/LayoutManager.d.ts.map +1 -0
  20. package/lib/core/MonacoWrapper.d.ts +63 -0
  21. package/lib/core/MonacoWrapper.d.ts.map +1 -0
  22. package/lib/core/SmartCodeEditor.d.ts +140 -0
  23. package/lib/core/SmartCodeEditor.d.ts.map +1 -0
  24. package/lib/dev-main.d.ts +2 -0
  25. package/lib/dev-main.d.ts.map +1 -0
  26. package/lib/index.cjs +242 -0
  27. package/lib/index.d.ts +5 -0
  28. package/lib/index.d.ts.map +1 -0
  29. package/lib/index.js +1369 -0
  30. package/lib/index.umd.cjs +242 -0
  31. package/lib/shims-vue.d.ts +4 -0
  32. package/lib/types/index.d.ts +101 -0
  33. package/lib/types/index.d.ts.map +1 -0
  34. package/lib/types/language.d.ts +37 -0
  35. package/lib/types/language.d.ts.map +1 -0
  36. package/lib/types/question.d.ts +75 -0
  37. package/lib/types/question.d.ts.map +1 -0
  38. package/lib/utils/loader.d.ts +9 -0
  39. package/lib/utils/loader.d.ts.map +1 -0
  40. package/lib/utils/markdown.d.ts +2 -0
  41. package/lib/utils/markdown.d.ts.map +1 -0
  42. package/package.json +72 -0
  43. package/src/adapters/vanilla/index.ts +7 -0
  44. package/src/adapters/vue/SmartCodeEditor.vue +1190 -0
  45. package/src/config/languages.ts +273 -0
  46. package/src/config/runnerStrategies.ts +261 -0
  47. package/src/config/runnerStrategies_v2.ts +182 -0
  48. package/src/config/themes.ts +37 -0
  49. package/src/core/BackendRunner.ts +329 -0
  50. package/src/core/CodeRunner.ts +107 -0
  51. package/src/core/LanguageManager.ts +108 -0
  52. package/src/core/LayoutManager.ts +268 -0
  53. package/src/core/MonacoWrapper.ts +173 -0
  54. package/src/core/SmartCodeEditor.ts +1015 -0
  55. package/src/dev-app.vue +488 -0
  56. package/src/dev-main.ts +7 -0
  57. package/src/index.ts +19 -0
  58. package/src/shims-vue.d.ts +4 -0
  59. package/src/types/index.ts +129 -0
  60. package/src/types/language.ts +44 -0
  61. package/src/types/question.ts +98 -0
  62. package/src/utils/loader.ts +69 -0
  63. package/src/utils/markdown.ts +89 -0
@@ -0,0 +1,242 @@
1
+ (function(g,C){typeof exports=="object"&&typeof module<"u"?C(exports):typeof define=="function"&&define.amd?define(["exports"],C):(g=typeof globalThis<"u"?globalThis:g||self,C(g.SmartCodeEditor={}))})(this,function(g){"use strict";function C(){return typeof window.monaco<"u"?Promise.resolve(window.monaco):new Promise((h,e)=>{const t=window,n=t.__SCE_MONACO_LOADER_URL__,i=t.__SCE_MONACO_BASE_PATH__,s=n?[n]:i?[`${String(i).replace(/\/$/,"")}/loader.js`]:["/package/min/vs/loader.js","/package/vs/loader.js"],l=r=>{if(r>=s.length){e(new Error("Monaco loader not found"));return}const c=s[r],u=document.createElement("script");u.src=c,u.onload=()=>{const p=c.replace(/\/loader\.js(\?.*)?$/,"");window.require.config({paths:{vs:p}}),window.require(["vs/editor/editor.main"],()=>{h(window.monaco)})},u.onerror=()=>{u.remove(),l(r+1)},document.body.appendChild(u)};l(0)})}function E(h,e){let t;return function(...n){clearTimeout(t),t=setTimeout(()=>{h.apply(this,n)},e)}}class P{constructor(e){this.editor=null,this.monaco=null,this.container=e}async initialize(e={}){this.monaco=await C(),this.editor=this.monaco.editor.create(this.container,{value:e.value||"",language:e.language||"javascript",theme:e.theme||"vs-dark",readOnly:e.readOnly||!1,fontSize:e.fontSize||14,minimap:e.minimap||{enabled:!0},lineNumbers:e.lineNumbers||"on",automaticLayout:e.automaticLayout!==!1,scrollBeyondLastLine:!1,roundedSelection:!0,padding:{top:16},suggestOnTriggerCharacters:e.suggestOnTriggerCharacters!==void 0?e.suggestOnTriggerCharacters:!0,quickSuggestions:e.quickSuggestions!==void 0?e.quickSuggestions:!0,tabSize:2})}setValue(e){this.editor&&this.editor.setValue(e)}getValue(){return this.editor?this.editor.getValue():""}updateModel(e,t,n="",i="default"){if(this.editor&&this.monaco){const a=this.editor.getModel(),s=n.startsWith(".")?n:`.${n}`,l=this.monaco.Uri.parse(`file:///${i}/main${s}`);let r=this.monaco.editor.getModel(l);r?(r.setValue(e),this.monaco.editor.setModelLanguage(r,t)):r=this.monaco.editor.createModel(e,t,l),this.editor.setModel(r),a&&a!==r&&a.dispose()}}setTheme(e){this.editor&&this.monaco&&this.monaco.editor.setTheme(e)}setReadOnly(e){this.editor&&this.editor.updateOptions({readOnly:e})}updateOptions(e){this.editor&&this.editor.updateOptions(e)}onDidChangeContent(e){this.editor&&this.editor.onDidChangeModelContent(()=>{e(this.getValue())})}layout(){this.editor&&this.editor.layout()}getMonaco(){return this.monaco}getEditor(){return this.editor}dispose(){this.editor&&(this.editor.dispose(),this.editor=null)}}class ${constructor(e,t=.48,n="vs-dark"){this.isDragging=!1,this.startX=0,this.startLeftWidth=0,this.handleMouseDown=i=>{this.isDragging=!0,this.startX=i.clientX,this.startLeftWidth=this.leftPanel.offsetWidth,this.splitter.style.background="#4CAF50",document.body.style.cursor="col-resize",document.body.style.userSelect="none",i.preventDefault()},this.handleMouseMove=i=>{if(!this.isDragging)return;const a=i.clientX-this.startX,s=this.startLeftWidth+a,l=this.container.offsetWidth,r=200,c=l-400-8;if(s>=r&&s<=c){const u=s/l;this.leftPanel.style.width=`${u*100}%`}},this.handleMouseUp=()=>{this.isDragging&&(this.isDragging=!1,this.splitter.style.background="#f5f5f5",document.body.style.cursor="",document.body.style.userSelect="")},this.container=e,this.leftPanel=document.createElement("div"),this.splitter=document.createElement("div"),this.rightPanel=document.createElement("div"),this.initLayout(t,n),this.initResizable()}initLayout(e,t){this.container.style.display="flex",this.container.style.height="100%",this.container.style.position="relative";const n=document.createElement("div");n.className="sce-editor-wrapper",n.style.display="flex",n.style.height="100%",n.style.width="100%",n.style.overflow="hidden",this.leftPanel.className="sce-question-panel",this.leftPanel.style.width=`${e*100}%`,this.leftPanel.style.minWidth="200px",this.leftPanel.style.overflow="auto",this.leftPanel.style.padding="14px 6px 14px 14px",this.leftPanel.style.boxSizing="border-box",this.splitter.className="sce-splitter",this.splitter.style.width="2px",this.splitter.style.cursor="col-resize",this.splitter.style.flexShrink="0",this.splitter.style.userSelect="none",this.splitter.style.margin="0 6px";const i=document.createElement("div");i.className="sce-right-container",i.style.flex="1",i.style.minWidth="400px",i.style.minHeight="0",i.style.display="flex",i.style.flexDirection="column",i.style.overflow="hidden",this.rightPanel.className="sce-editor-panel",this.rightPanel.style.flex="1",this.rightPanel.style.minHeight="0",this.rightPanel.style.overflow="hidden",this.rightPanel.style.position="relative",this.rightPanel.style.display="flex",this.rightPanel.style.flexDirection="column",this.setTheme(t),i.appendChild(this.rightPanel),n.appendChild(this.leftPanel),n.appendChild(this.splitter),n.appendChild(i),this.container.appendChild(n)}initResizable(){this.splitter.addEventListener("mousedown",this.handleMouseDown),document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("mouseup",this.handleMouseUp)}setLeftContent(e){typeof e=="string"?(this.leftPanel.innerHTML=e,this.leftPanel.style.overflow="auto"):(this.leftPanel.innerHTML="",this.leftPanel.appendChild(e),e.classList.contains("sce-question-markdown")?this.leftPanel.style.overflow="hidden":this.leftPanel.style.overflow="auto")}getRightContainer(){return this.rightPanel}setQuestionPanelVisible(e){e?(this.leftPanel.style.display="block",this.splitter.style.display="block"):(this.leftPanel.style.display="none",this.splitter.style.display="none")}setSplitRatio(e){this.leftPanel.style.width=`${e*100}%`}setTheme(e){const t=e==="vs-dark";t?(this.leftPanel.style.background="#1e1e1e",this.leftPanel.style.color="#d4d4d4",this.splitter.style.background="#252526"):(this.leftPanel.style.background="#ffffff",this.leftPanel.style.color="#333333",this.splitter.style.background="#f5f5f5");const n=this.leftPanel.querySelector(".sce-markdown-editor"),i=this.leftPanel.querySelector(".sce-markdown-preview"),a=this.leftPanel.querySelectorAll(".sce-markdown-label"),s=this.leftPanel.querySelectorAll(".sce-markdown-tab");n&&(n.style.background=t?"#1e1e1e":"#ffffff",n.style.color=t?"#d4d4d4":"#333333",n.style.border=t?"1px solid #333":"1px solid #ddd"),i&&(i.style.background=t?"#1b1b1b":"#ffffff",i.style.color=t?"#d4d4d4":"#333333"),a.forEach(l=>{l.style.color=t?"#c5c5c5":"#666666"}),s.forEach(l=>{const r=l,c=r.classList.contains("active");r.style.border=t?"1px solid #3a3a3a":"1px solid #ddd",r.style.background=c?t?"#2d2d30":"#f3f3f3":t?"#1f1f1f":"#ffffff",r.style.color=t?"#d4d4d4":"#333333",r.style.borderRadius="6px",r.style.padding="4px 10px",r.style.fontSize="12px",r.style.cursor="pointer"})}destroy(){document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("mouseup",this.handleMouseUp),this.container.innerHTML=""}}const k=[{id:"javascript",name:"JavaScript",monacoId:"javascript",extensions:[".js"],fallbackTemplate:`// JavaScript 示例
2
+ console.log("Hello, World!");
3
+
4
+ // 定义一个函数
5
+ function fibonacci(n) {
6
+ if (n <= 1) return n;
7
+ return fibonacci(n - 1) + fibonacci(n - 2);
8
+ }
9
+
10
+ console.log("斐波那契数列前10项:");
11
+ for (let i = 0; i < 10; i++) {
12
+ console.log(\`F(\${i}) = \${fibonacci(i)}\`);
13
+ }`,canRun:!0},{id:"typescript",name:"TypeScript",monacoId:"typescript",extensions:[".ts"],fallbackTemplate:`// TypeScript 示例
14
+ interface User {
15
+ name: string;
16
+ age: number;
17
+ }
18
+
19
+ const user: User = {
20
+ name: "张三",
21
+ age: 25
22
+ };
23
+
24
+ console.log(\`用户: \${user.name}, 年龄: \${user.age}\`);`,canRun:!0},{id:"python",name:"Python",monacoId:"python",extensions:[".py"],fallbackTemplate:`# Python 示例
25
+ print("Hello, World!")
26
+
27
+ # 列表推导式
28
+ squares = [x**2 for x in range(10)]
29
+ print("前10个平方数:", squares)
30
+
31
+ # 定义一个类
32
+ class Person:
33
+ def __init__(self, name, age):
34
+ self.name = name
35
+ self.age = age
36
+
37
+ def greet(self):
38
+ return f"你好,我是{self.name},今年{self.age}岁"
39
+
40
+ person = Person("李四", 30)
41
+ print(person.greet())`,canRun:!0},{id:"html",name:"HTML",monacoId:"html",fallbackTemplate:`<!DOCTYPE html>
42
+ <html lang="zh-CN">
43
+ <head>
44
+ <meta charset="UTF-8">
45
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
46
+ <title>Hello HTML</title>
47
+ </head>
48
+ <body>
49
+ <h1>欢迎使用智能代码编辑器</h1>
50
+ <p>这是一个 HTML 示例</p>
51
+ </body>
52
+ </html>`,canRun:!1,extensions:[".html"]},{id:"css",name:"CSS",monacoId:"css",fallbackTemplate:`/* CSS 示例 */
53
+ body {
54
+ font-family: 'Arial', sans-serif;
55
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
56
+ color: white;
57
+ padding: 20px;
58
+ }
59
+
60
+ .container {
61
+ max-width: 1200px;
62
+ margin: 0 auto;
63
+ background: rgba(255, 255, 255, 0.1);
64
+ border-radius: 10px;
65
+ padding: 30px;
66
+ }
67
+
68
+ h1 {
69
+ font-size: 2.5rem;
70
+ margin-bottom: 20px;
71
+ }`,canRun:!1,extensions:[".css"]},{id:"java",name:"Java",monacoId:"java",fallbackTemplate:`public class HelloWorld {
72
+ public static void main(String[] args) {
73
+ System.out.println("Hello, World!");
74
+
75
+ // 数组示例
76
+ int[] numbers = {1, 2, 3, 4, 5};
77
+ int sum = 0;
78
+ for (int num : numbers) {
79
+ sum += num;
80
+ }
81
+ System.out.println("数组总和: " + sum);
82
+ }
83
+ }`,canRun:!0,extensions:[".java"]},{id:"cpp",name:"C++",monacoId:"cpp",fallbackTemplate:`#include <iostream>
84
+ #include <vector>
85
+ using namespace std;
86
+
87
+ int main() {
88
+ cout << "Hello, World!" << endl;
89
+
90
+ // 向量示例
91
+ vector<int> vec = {1, 2, 3, 4, 5};
92
+ int sum = 0;
93
+ for(int num : vec) {
94
+ sum += num;
95
+ }
96
+ cout << "向量总和: " << sum << endl;
97
+
98
+ return 0;
99
+ }`,canRun:!0,extensions:[".cpp",".cc",".cxx"]},{id:"go",name:"Go",monacoId:"go",fallbackTemplate:`package main
100
+
101
+ import "fmt"
102
+
103
+ func main() {
104
+ fmt.Println("Hello, World!")
105
+
106
+ // 切片示例
107
+ numbers := []int{1, 2, 3, 4, 5}
108
+ sum := 0
109
+ for _, num := range numbers {
110
+ sum += num
111
+ }
112
+ fmt.Printf("切片总和: %d\\n", sum)
113
+ }`,canRun:!0,extensions:[".go"]},{id:"rust",name:"Rust",monacoId:"rust",fallbackTemplate:`fn main() {
114
+ println!("Hello, World!");
115
+
116
+ // 向量示例
117
+ let numbers = vec![1, 2, 3, 4, 5];
118
+ let sum: i32 = numbers.iter().sum();
119
+ println!("总和: {}", sum);
120
+ }`,canRun:!0,extensions:[".rs"]},{id:"c",name:"C",monacoId:"c",fallbackTemplate:`#include <stdio.h>
121
+
122
+ int main() {
123
+ printf("Hello, World!\\n");
124
+
125
+ // 数组示例
126
+ int numbers[] = {1, 2, 3, 4, 5};
127
+ int sum = 0;
128
+ int size = sizeof(numbers) / sizeof(numbers[0]);
129
+
130
+ for(int i = 0; i < size; i++) {
131
+ sum += numbers[i];
132
+ }
133
+
134
+ printf("数组总和: %d\\n", sum);
135
+ return 0;
136
+ }`,canRun:!0,extensions:[".c"]},{id:"sql",name:"SQL",monacoId:"sql",fallbackTemplate:`-- SQL 示例
137
+ SELECT
138
+ users.name,
139
+ users.email,
140
+ COUNT(orders.id) as order_count,
141
+ SUM(orders.amount) as total_amount
142
+ FROM users
143
+ LEFT JOIN orders ON users.id = orders.user_id
144
+ WHERE users.created_at >= '2024-01-01'
145
+ GROUP BY users.id, users.name, users.email
146
+ HAVING COUNT(orders.id) > 0
147
+ ORDER BY total_amount DESC
148
+ LIMIT 10;`,canRun:!1,extensions:[".sql"]}];function N(h){return k.find(e=>e.id===h)}function W(){return k}class H{constructor(e="javascript"){this.languages=new Map,k.forEach(n=>{this.languages.set(n.id,n)});const t=this.languages.get(e);if(!t)throw new Error(`Language "${e}" not found in config`);this.currentLanguage=t}getLanguage(e){return this.languages.get(e)}getAllLanguages(){return Array.from(this.languages.values())}switchLanguage(e){const t=this.languages.get(e);if(!t)throw new Error(`Language "${e}" not supported`);return this.currentLanguage=t,this.currentLanguage}getCurrentLanguage(){return this.currentLanguage}isSupported(e){return this.languages.has(e)}getRunnableLanguages(){return Array.from(this.languages.values()).filter(e=>e.canRun)}getTemplate(e,t,n){var a,s;if(n&&n[e]!==void 0&&n[e]!==null)return n[e];if(((a=t==null?void 0:t.languageTemplates)==null?void 0:a[e])!==void 0&&((s=t==null?void 0:t.languageTemplates)==null?void 0:s[e])!==null)return t.languageTemplates[e];const i=this.languages.get(e);return i&&i.fallbackTemplate?i.fallbackTemplate:""}}async function R(h,e){const t=performance.now();try{if(!e||e.length===0){const d=[],o={log:(...f)=>{d.push(f.map(w=>typeof w=="object"?JSON.stringify(w,null,2):String(w)).join(" "))},error:(...f)=>{d.push("ERROR: "+f.join(" "))},warn:(...f)=>{d.push("WARN: "+f.join(" "))}};new Function("console",h)(o);const m=performance.now()-t;return{output:d.join(`
149
+ `)||"(无输出)",executionTime:m,status:"success"}}const n=[],i=[],a=`
150
+ ${h}
151
+
152
+ // 尝试找到入口函数
153
+ let mainFn = null;
154
+ // 优先级 1: solution 函数
155
+ if (typeof solution === 'function') mainFn = solution;
156
+ // 优先级 2: twoSum (针对示例)
157
+ else if (typeof twoSum === 'function') mainFn = twoSum;
158
+ // 优先级 3: 寻找最后一个定义的函数 (简单启发式,可能不准确)
159
+
160
+ if (!mainFn) {
161
+ // 如果没找到具名函数,尝试返回一个错误
162
+ throw new Error("未找到入口函数 (请定义 solution 或 twoSum 函数)");
163
+ }
164
+
165
+ return mainFn;
166
+ `;let s=(d,o)=>{const b=o.map(m=>typeof m=="object"?JSON.stringify(m,null,2):String(m)).join(" ");n.push(b)};const l={log:(...d)=>s("log",d),error:(...d)=>s("error",d),warn:(...d)=>s("warn",d)},c=new Function("console",a)(l);for(const d of e){const o=[],b=performance.now();let m="error",f,w;s=(v,x)=>{const _=x.map(M=>typeof M=="object"?JSON.stringify(M,null,2):String(M)).join(" ");o.push(_)};try{let v;Array.isArray(d.input)?v=c(...d.input):v=c(d.input),f=v;let x=!1;if(d.expected!==void 0)try{x=JSON.stringify(v)===JSON.stringify(d.expected)}catch{x=v===d.expected}else x=!0;m=x?"passed":"failed"}catch(v){m="error",w=v.message,f=void 0}const I=performance.now();i.push({id:d.id,status:m,input:d.input,output:f,expected:d.expected,log:o.join(`
167
+ `),error:w,executionTime:I-b})}const u=performance.now()-t,p=i.some(d=>d.status==="error"),y=i.some(d=>d.status==="failed");return{output:n.join(`
168
+ `),executionTime:u,status:p||y?"error":"success",testResults:i}}catch(n){const i=performance.now()-t;return{output:"",error:n.message||String(n),executionTime:i,status:"error"}}}async function z(h){const e=performance.now();try{return{output:"Python 运行功能需要加载 Pyodide (暂未实现)",executionTime:performance.now()-e,status:"error",error:"Pyodide 未加载"}}catch(t){return{output:"",error:t.message,executionTime:performance.now()-e,status:"error"}}}async function L(h,e){const t=performance.now();try{return{output:`${e} 远程运行功能需要配置编译服务 (暂未实现)`,executionTime:performance.now()-t,status:"error",error:"远程编译服务未配置"}}catch(n){return{output:"",error:n.message,executionTime:performance.now()-t,status:"error"}}}const V={javascript:R,typescript:R,python:z,java:h=>L(h,"Java"),cpp:h=>L(h,"C++"),go:h=>L(h,"Go")};function j(h){return V[h]}class A{constructor(e=5e3){this.abortController=null,this.timeout=e}async run(e,t,n){const i=j(t);if(!i)return{output:"",error:`语言 "${t}" 不支持运行`,executionTime:0,status:"error"};this.abortController=new AbortController;const a=setTimeout(()=>{var s;(s=this.abortController)==null||s.abort()},this.timeout);try{const s=await Promise.race([i(e,n),this.createTimeoutPromise()]);return clearTimeout(a),s}catch(s){return clearTimeout(a),s.name==="AbortError"?{output:"",error:`执行超时(${this.timeout}ms)`,executionTime:this.timeout,status:"timeout"}:{output:"",error:s.message||String(s),executionTime:0,status:"error"}}finally{this.abortController=null}}createTimeoutPromise(){return new Promise((e,t)=>{var n;(n=this.abortController)==null||n.signal.addEventListener("abort",()=>{const i=new Error("Execution timeout");i.name="AbortError",t(i)})})}cancel(){var e;(e=this.abortController)==null||e.abort()}setTimeout(e){this.timeout=e}destroy(){this.cancel()}}function O(h){return h.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function S(h){let e=h;return e=e.replace(/`([^`]+)`/g,"<code>$1</code>"),e=e.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),e=e.replace(/\*([^*]+)\*/g,"<em>$1</em>"),e=e.replace(/_([^_]+)_/g,"<em>$1</em>"),e=e.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'),e}function D(h){const e=h||"",t=[];let n=e.replace(/```(?:[\w-]+)?\n([\s\S]*?)```/g,(c,u)=>{const p=O(u.trimEnd()),y=`@@CODEBLOCK_${t.length}@@`;return t.push(`<pre><code>${p}</code></pre>`),y});n=O(n);const i=n.split(/\r?\n/),a=[];let s=!1;const l=()=>{s&&(a.push("</ul>"),s=!1)};for(const c of i){const u=c.trim();if(!u){l();continue}const p=u.match(/^(#{1,6})\s+(.*)$/);if(p){l();const d=p[1].length;a.push(`<h${d}>${S(p[2])}</h${d}>`);continue}const y=u.match(/^[-*+]\s+(.*)$/);if(y){s||(a.push("<ul>"),s=!0),a.push(`<li>${S(y[1])}</li>`);continue}l(),a.push(`<p>${S(u)}</p>`)}l();let r=a.join(`
169
+ `);return t.forEach((c,u)=>{r=r.replace(`@@CODEBLOCK_${u}@@`,c)}),r}class q{constructor(e){if(this.monacoWrapper=null,this.layoutManager=null,this.initialized=!1,this._pendingLanguage=null,this._pendingValue=null,this.resizeObserver=null,this.loadingMask=null,this.toolbar=null,this.langSelect=null,this.markdownEditor=null,this.markdownPreview=null,this.testCases=[],this.id=`sce_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,this.options=e,typeof e.container=="string"){const t=document.querySelector(e.container);if(!t)throw new Error(`Container "${e.container}" not found`);this.container=t}else this.container=e.container;this.languageManager=new H(e.language||"javascript"),this.codeRunner=new A(e.runTimeout||5e3),this.init()}showLoading(){if(this.loadingMask)return;this.loadingMask=document.createElement("div"),this.loadingMask.className="sce-loading-mask",this.loadingMask.style.cssText=`
170
+ position: absolute;
171
+ top: 0;
172
+ left: 0;
173
+ width: 100%;
174
+ height: 100%;
175
+ background: ${this.options.theme==="vs-dark"?"#1e1e1e":"#ffffff"};
176
+ display: flex;
177
+ align-items: center;
178
+ justify-content: center;
179
+ z-index: 1000;
180
+ color: ${this.options.theme==="vs-dark"?"#d4d4d4":"#333333"};
181
+ font-size: 14px;
182
+ font-family: -apple-system, system-ui, sans-serif;
183
+ `;const e=document.createElement("div");e.className="sce-spinner",e.textContent="Loading...",this.loadingMask.appendChild(e),this.container.style.position="relative",this.container.appendChild(this.loadingMask)}hideLoading(){this.loadingMask&&this.loadingMask.parentNode&&(this.loadingMask.parentNode.removeChild(this.loadingMask),this.loadingMask=null)}createMarkdownPanel(e){const t=document.createElement("div");t.className="sce-question-markdown",t.style.display="flex",t.style.flexDirection="column",t.style.height="100%",t.style.minHeight="0",t.style.gap="12px",t.style.overflow="hidden";const n=e.editable!==!1,i=n&&e.showEditor!==!1,a=n?e.showPreview!==!1:!0,s=e.value||"";let l=null,r=null,c=null,u=null,p=null;const y=()=>{if(r&&u){const o=r.style.display!=="none";u.classList.toggle("active",o)}if(c&&p){const o=c.style.display!=="none";p.classList.toggle("active",o)}},d=o=>{r&&(r.style.display=o===r?"flex":"none"),c&&(c.style.display=o===c?"flex":"none"),y()};if(n&&i&&a){const o=document.createElement("div");o.className="sce-markdown-tabs",o.style.display="flex",o.style.gap="8px",u=document.createElement("button"),u.type="button",u.className="sce-markdown-tab active",u.textContent="编辑",p=document.createElement("button"),p.type="button",p.className="sce-markdown-tab active",p.textContent="预览",o.appendChild(u),o.appendChild(p),t.appendChild(o)}if(i){r=document.createElement("div"),r.className="sce-markdown-editor-section",r.style.display="flex",r.style.flexDirection="column",r.style.flex="1",r.style.minHeight="0";const o=document.createElement("textarea");o.className="sce-markdown-editor",o.value=s,o.placeholder=e.placeholder||"在此编辑 Markdown...",o.readOnly=e.editable===!1,o.style.width="100%",o.style.flex="1",o.style.minHeight="120px",o.style.resize="none",o.style.boxSizing="border-box",o.style.padding="10px",o.style.borderRadius="6px",o.style.fontFamily="ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",o.style.fontSize="12px",o.style.lineHeight="1.5",r.appendChild(o),t.appendChild(r),this.markdownEditor=o;const b=E(m=>{l&&l(m),e.onChange&&e.onChange(m)},150);o.addEventListener("input",()=>{b(o.value)})}if(a){c=document.createElement("div"),c.className="sce-markdown-preview-section",c.style.display="flex",c.style.flexDirection="column",c.style.flex="1",c.style.minHeight="0";const o=document.createElement("div");o.className="sce-markdown-preview",o.style.flex="1",o.style.minHeight="0",o.style.overflow="auto",o.style.padding="10px",o.style.borderRadius="6px",o.style.fontFamily="-apple-system, system-ui, sans-serif",o.style.fontSize="13px",o.style.lineHeight="1.6",l=b=>{o.innerHTML=D(b)},l(s),c.appendChild(o),t.appendChild(c),this.markdownPreview=o}if(u&&p&&(u.addEventListener("click",()=>{d(r)}),p.addEventListener("click",()=>{d(c)}),d(r)),!i&&!a){const o=document.createElement("div");o.textContent="未启用 Markdown 编辑/预览",t.appendChild(o)}return t}async init(){var e;try{if(this.showLoading(),this.options.showQuestionPanel!==!1){if(this.layoutManager=new $(this.container,this.options.defaultSplitRatio||.5,this.options.theme||"vs-dark"),this.options.questionMarkdown){const r=this.createMarkdownPanel(this.options.questionMarkdown);this.layoutManager.setLeftContent(r),this.layoutManager.setTheme(this.options.theme||"vs-dark")}else this.options.questionContent&&this.layoutManager.setLeftContent(this.options.questionContent);const s=this.layoutManager.getRightContainer(),l=document.createElement("div");l.className="sce-monaco-container",l.style.flex="1",l.style.minHeight="0",l.style.overflow="hidden",l.style.position="relative",s.appendChild(l),this.monacoWrapper=new P(l)}else{this.container.style.display="flex",this.container.style.flexDirection="column";const s=document.createElement("div");s.className="sce-monaco-container",s.style.flex="1",s.style.minHeight="0",s.style.overflow="hidden",s.style.position="relative",this.container.appendChild(s),this.monacoWrapper=new P(s)}const t=this.languageManager.getCurrentLanguage(),n=this.options.value!==void 0&&this.options.value!==null?this.options.value:this.languageManager.getTemplate(t.id,this.options.questionConfig,this.options.languageTemplates);console.log("🎨 SmartCodeEditor 初始化:",{hasValue:this.options.value!==void 0,valueLength:(e=this.options.value)==null?void 0:e.length,hasQuestionConfig:!!this.options.questionConfig,hasLanguageTemplates:!!this.options.languageTemplates,initialValuePreview:(n==null?void 0:n.substring(0,50))+"..."}),await this.monacoWrapper.initialize({value:n,language:t.monacoId,theme:this.options.theme||"vs-dark",readOnly:this.options.readOnly||!1,automaticLayout:!1,suggestOnTriggerCharacters:this.options.suggestOnTriggerCharacters,quickSuggestions:this.options.quickSuggestions});const i=t.extensions?t.extensions[0]:"";this.monacoWrapper.updateModel(n,t.monacoId,i,this.id);const a=this.languageManager.getCurrentLanguage();if(a.id!==t.id){const s=a.extensions?a.extensions[0]:"";this.monacoWrapper.updateModel(this.getValue(),a.monacoId,s,this.id)}if(this._pendingValue!==null&&(this.monacoWrapper.setValue(this._pendingValue),this._pendingValue=null),this.options.onChange){const s=E(this.options.onChange,300);this.monacoWrapper.onDidChangeContent(s)}this.initialized=!0,this._pendingLanguage&&(this.setLanguage(this._pendingLanguage),this._pendingLanguage=null),this._pendingValue!==null&&(this.monacoWrapper.setValue(this._pendingValue),this._pendingValue=null),this.createToolbar(),typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(()=>{requestAnimationFrame(()=>{this.layout()})}),this.resizeObserver.observe(this.container)),this.layout()}catch(t){throw console.error("Failed to initialize SmartCodeEditor:",t),t}finally{this.hideLoading()}}createToolbar(){if(!this.monacoWrapper)return;const e=this.layoutManager?this.layoutManager.getRightContainer():this.container,t=document.createElement("div");this.toolbar=t,t.className="sce-toolbar";const n=this.options.theme==="vs-dark",i=n?"#2d2d30":"#fff",a=n?"#454545":"#f3f3f3";if(t.style.cssText=`
184
+ display: flex;
185
+ align-items: center;
186
+ gap: 12px;
187
+ padding: 8px 16px;
188
+ background: ${i};
189
+ border-bottom: 1px solid ${a};
190
+ transition: all 0.2s;
191
+ flex-shrink: 0;
192
+ `,this.options.enableLanguageSwitch!==!1){const s=this.createLanguageSelector();t.appendChild(s)}if(this.options.enableRun!==!1){const s=this.createRunButton();t.appendChild(s)}if(this.options.enableSubmit!==!1){const s=this.createSubmitButton();t.appendChild(s)}e.insertBefore(t,e.firstChild)}createLanguageSelector(){const e=document.createElement("div");e.style.display="flex",e.style.alignItems="center",e.style.gap="8px";const t=document.createElement("span");t.textContent="语言:",t.style.color=this.options.theme==="vs-dark"?"#ccc":"#666",t.style.fontSize="13px";const n=document.createElement("select");this.langSelect=n;const i=this.options.theme==="vs-dark",a=i?"#3c3c3c":"#ffffff",s=i?"#ccc":"#333",l=i?"#454545":"#ccc";n.style.cssText=`
193
+ padding: 4px 8px;
194
+ border: 1px solid ${l};
195
+ background: ${a};
196
+ color: ${s};
197
+ border-radius: 4px;
198
+ cursor: pointer;
199
+ font-size: 13px;
200
+ `;let r=this.languageManager.getAllLanguages();return this.options.supportedLanguages&&this.options.supportedLanguages.length>0&&(r=r.filter(c=>this.options.supportedLanguages.includes(c.id))),r.forEach(c=>{const u=document.createElement("option");u.value=c.id,u.textContent=`${c.icon||""} ${c.name}`.trim(),c.id===this.languageManager.getCurrentLanguage().id&&(u.selected=!0),n.appendChild(u)}),n.addEventListener("change",()=>{this.setLanguage(n.value)}),e.appendChild(t),e.appendChild(n),e}createRunButton(){const e=document.createElement("button");return e.innerHTML="<span>▶</span> 运行",e.style.cssText=`
201
+ padding: 6px 16px;
202
+ border: none;
203
+ background: #0e639c;
204
+ color: white;
205
+ border-radius: 4px;
206
+ cursor: pointer;
207
+ font-size: 13px;
208
+ font-weight: 500;
209
+ margin-left: auto;
210
+ display: flex;
211
+ align-items: center;
212
+ gap: 6px;
213
+ transition: background 0.2s;
214
+ `,e.addEventListener("click",async()=>{const t=e.innerHTML;try{e.disabled=!0,e.style.background="#0e639c80",e.style.cursor="not-allowed",e.innerHTML='<span class="sce-btn-spinner"></span> 运行中...',await this.run()}finally{e.disabled=!1,e.style.background="#0e639c",e.style.cursor="pointer",e.innerHTML=t}}),e.addEventListener("mouseenter",()=>{e.disabled||(e.style.background="#1177bb")}),e.addEventListener("mouseleave",()=>{e.disabled||(e.style.background="#0e639c")}),this.injectSpinnerStyle(),e}createSubmitButton(){const e=document.createElement("button");return e.textContent="提交",e.title="提交代码进行评测",e.style.cssText=`
215
+ padding: 6px 16px;
216
+ border: none;
217
+ background: #4caf50;
218
+ color: white;
219
+ border-radius: 4px;
220
+ cursor: pointer;
221
+ font-size: 13px;
222
+ font-weight: 500;
223
+ margin-left: 8px;
224
+ display: flex;
225
+ align-items: center;
226
+ gap: 6px;
227
+ transition: background 0.2s;
228
+ `,e.addEventListener("click",async()=>{if(this.options.onSubmit){const t=e.textContent||"提交";try{e.disabled=!0,e.style.background="#4caf5080",e.style.cursor="not-allowed",e.innerHTML='<span class="sce-btn-spinner"></span> 提交中...',await this.options.onSubmit(this.getValue(),this.getLanguage())}finally{e.disabled=!1,e.style.background="#4caf50",e.style.cursor="pointer",e.textContent=t}}}),e.addEventListener("mouseenter",()=>{e.disabled||(e.style.background="#43a047")}),e.addEventListener("mouseleave",()=>{e.disabled||(e.style.background="#4caf50")}),e}injectSpinnerStyle(){if(document.getElementById("sce-btn-spinner-style"))return;const e=document.createElement("style");e.id="sce-btn-spinner-style",e.innerHTML=`
229
+ @keyframes sce-spin {
230
+ 0% { transform: rotate(0deg); }
231
+ 100% { transform: rotate(360deg); }
232
+ }
233
+ .sce-btn-spinner {
234
+ display: inline-block;
235
+ width: 12px;
236
+ height: 12px;
237
+ border: 2px solid rgba(255,255,255,0.3);
238
+ border-radius: 50%;
239
+ border-top-color: #fff;
240
+ animation: sce-spin 1s ease-in-out infinite;
241
+ }
242
+ `,document.head.appendChild(e)}getValue(){var e;return((e=this.monacoWrapper)==null?void 0:e.getValue())||""}setValue(e){if(!this.monacoWrapper||!this.initialized){this._pendingValue=e;return}this.monacoWrapper.setValue(e)}getLanguage(){return this.languageManager.getCurrentLanguage().id}setLanguage(e){var s;if(!this.monacoWrapper||!this.initialized){this._pendingLanguage=e;return}const t=this.languageManager.switchLanguage(e),n=this.getValue(),i=t.extensions?t.extensions[0]:"";(s=this.monacoWrapper)==null||s.updateModel(n,t.monacoId,i,this.id);const a=this.languageManager.getTemplate(e,this.options.questionConfig,this.options.languageTemplates);this.setValue(a),this.options.onLanguageChange&&this.options.onLanguageChange(e)}getSupportedLanguages(){return this.languageManager.getAllLanguages()}setTheme(e){var t,n;if((t=this.monacoWrapper)==null||t.setTheme(e),(n=this.layoutManager)==null||n.setTheme(e),this.options.theme=e,this.toolbar){const i=e==="vs-dark";this.toolbar.style.background=i?"#2d2d30":"#f3f3f3",this.toolbar.style.borderBottom=i?"1px solid #454545":"1px solid #e0e0e0"}if(this.langSelect){const i=e==="vs-dark";this.langSelect.style.background=i?"#3c3c3c":"#ffffff",this.langSelect.style.color=i?"#ccc":"#333",this.langSelect.style.borderColor=i?"#454545":"#ccc",this.langSelect.previousElementSibling instanceof HTMLElement&&(this.langSelect.previousElementSibling.style.color=i?"#ccc":"#666")}}getTheme(){return this.options.theme||"vs-dark"}setQuestionContent(e){var t;(t=this.layoutManager)==null||t.setLeftContent(e),this.markdownEditor=null,this.markdownPreview=null}setQuestionMarkdown(e,t){if(!this.layoutManager)return;const n={...this.options.questionMarkdown||{},...t||{},value:e},i=this.createMarkdownPanel(n);this.layoutManager.setLeftContent(i),this.options.questionMarkdown=n,this.layoutManager.setTheme(this.options.theme||"vs-dark")}showQuestionPanel(){var e;(e=this.layoutManager)==null||e.setQuestionPanelVisible(!0)}hideQuestionPanel(){var e;(e=this.layoutManager)==null||e.setQuestionPanelVisible(!1)}setTestCases(e){this.testCases=e}async run(e){const t=this.getValue(),n=this.getLanguage(),i=this.languageManager.getCurrentLanguage();if(!i.canRun){const a={output:"",error:`语言 "${i.name}" 不支持运行`,executionTime:0,status:"error"};return this.options.onRun&&this.options.onRun(a),a}if(this.options.customRunner){const a=e||this.testCases;try{const s=await this.options.customRunner(t,n,a);return this.options.onRun&&this.options.onRun(s),s}catch(s){const l={output:"",error:s.message||"自定义运行器执行失败",executionTime:0,status:"error"};return this.options.onRun&&this.options.onRun(l),l}}try{const a=e||this.testCases,s=await this.codeRunner.run(t,n,a);return this.options.onRun&&this.options.onRun(s),s}catch(a){const s={output:"",error:a.message,executionTime:0,status:"error"};return this.options.onRun&&this.options.onRun(s),s}}cancelRun(){this.codeRunner.cancel()}resize(){var e;(e=this.monacoWrapper)==null||e.layout()}setSplitRatio(e){var t,n;(t=this.layoutManager)==null||t.setSplitRatio(e),(n=this.monacoWrapper)==null||n.layout()}layout(){var e;(e=this.monacoWrapper)==null||e.layout()}updateConfig(e){var n;const t={};e.questionConfig&&(this.options.questionConfig=e.questionConfig),e.languageTemplates&&(this.options.languageTemplates=e.languageTemplates),e.supportedLanguages&&(this.options.supportedLanguages=e.supportedLanguages,this.refreshLanguageSelector()),e.suggestOnTriggerCharacters!==void 0&&(this.options.suggestOnTriggerCharacters=e.suggestOnTriggerCharacters,t.suggestOnTriggerCharacters=e.suggestOnTriggerCharacters),e.quickSuggestions!==void 0&&(this.options.quickSuggestions=e.quickSuggestions,t.quickSuggestions=e.quickSuggestions),Object.keys(t).length>0&&((n=this.monacoWrapper)==null||n.updateOptions(t))}refreshLanguageSelector(){if(!this.langSelect)return;this.langSelect.innerHTML="";let e=this.languageManager.getAllLanguages();this.options.supportedLanguages&&this.options.supportedLanguages.length>0&&(e=e.filter(t=>this.options.supportedLanguages.includes(t.id))),e.forEach(t=>{const n=document.createElement("option");n.value=t.id,n.textContent=`${t.icon||""} ${t.name}`.trim(),t.id===this.languageManager.getCurrentLanguage().id&&(n.selected=!0),this.langSelect.appendChild(n)})}destroy(){var e,t,n;(e=this.resizeObserver)==null||e.disconnect(),(t=this.monacoWrapper)==null||t.dispose(),(n=this.layoutManager)==null||n.destroy(),this.codeRunner.destroy()}}const T={light:{id:"vs",name:"VS Light",displayName:"浅色主题"},dark:{id:"vs-dark",name:"VS Dark",displayName:"深色主题"},"high-contrast":{id:"hc-black",name:"High Contrast",displayName:"高对比度"}};function F(){return Object.values(T)}function U(h){return T[h]}g.LANGUAGE_CONFIGS=k,g.SmartCodeEditor=q,g.THEME_CONFIGS=T,g.getAllLanguages=W,g.getAllThemes=F,g.getLanguageConfig=N,g.getThemeConfig=U,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"})});
@@ -0,0 +1,4 @@
1
+ declare module "*.vue" {
2
+ const component: any;
3
+ export default component;
4
+ }
@@ -0,0 +1,101 @@
1
+ export * from './language';
2
+ export * from './question';
3
+ /**
4
+ * 代码运行结果
5
+ */
6
+ /**
7
+ * UI 绑定的测试用例(支持编辑)
8
+ */
9
+ export interface UITestCase {
10
+ id: string | number;
11
+ label?: string;
12
+ inputs: {
13
+ name: string;
14
+ value: string;
15
+ }[];
16
+ expected: string;
17
+ }
18
+ /**
19
+ * 运行时的测试用例
20
+ */
21
+ export interface TestCase {
22
+ id: string | number;
23
+ input: any[];
24
+ expected?: any;
25
+ }
26
+ /**
27
+ * 单个用例的运行结果
28
+ */
29
+ export interface TestCaseResult {
30
+ id: string | number;
31
+ status: "passed" | "failed" | "error";
32
+ input: any[];
33
+ output: any;
34
+ expected?: any;
35
+ log?: string;
36
+ error?: string;
37
+ executionTime?: number;
38
+ }
39
+ /**
40
+ * 代码运行结果
41
+ */
42
+ export interface RunResult {
43
+ output: string;
44
+ error?: string;
45
+ executionTime: number;
46
+ status: "success" | "error" | "timeout";
47
+ testResults?: TestCaseResult[];
48
+ }
49
+ /**
50
+ * 运行策略函数类型
51
+ */
52
+ export type RunnerStrategy = (code: string, testCases?: TestCase[]) => Promise<RunResult>;
53
+ /**
54
+ * 编辑器选项
55
+ */
56
+ export interface SmartCodeEditorOptions {
57
+ container: HTMLElement | string;
58
+ language?: string;
59
+ theme?: string;
60
+ value?: string;
61
+ readOnly?: boolean;
62
+ showQuestionPanel?: boolean;
63
+ questionContent?: string;
64
+ questionMarkdown?: import('./question').QuestionMarkdownOptions;
65
+ defaultSplitRatio?: number;
66
+ supportedLanguages?: string[];
67
+ enableLanguageSwitch?: boolean;
68
+ enableRun?: boolean;
69
+ disableLocalRun?: boolean;
70
+ customRunner?: (code: string, language: string, testCases?: TestCase[]) => Promise<RunResult>;
71
+ runTimeout?: number;
72
+ enableSubmit?: boolean;
73
+ /** 题目完整配置(可选) */
74
+ questionConfig?: import('./question').QuestionConfig;
75
+ /** 自定义语言模板映射(可选,会覆盖 questionConfig) */
76
+ languageTemplates?: import('./question').LanguageTemplates;
77
+ onChange?: (value: string) => void;
78
+ onRun?: (result: RunResult) => void;
79
+ onSubmit?: (code: string, language: string) => void;
80
+ onLanguageChange?: (language: string) => void;
81
+ suggestOnTriggerCharacters?: boolean;
82
+ quickSuggestions?: boolean | object;
83
+ }
84
+ /**
85
+ * Monaco Editor 配置选项
86
+ */
87
+ export interface MonacoEditorOptions {
88
+ language?: string;
89
+ theme?: string;
90
+ value?: string;
91
+ readOnly?: boolean;
92
+ minimap?: {
93
+ enabled: boolean;
94
+ };
95
+ fontSize?: number;
96
+ lineNumbers?: "on" | "off";
97
+ automaticLayout?: boolean;
98
+ suggestOnTriggerCharacters?: boolean;
99
+ quickSuggestions?: boolean | object;
100
+ }
101
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * 语言静态元数据
3
+ * 定义语言的基础属性(图标、Monaco ID、文件扩展名等)
4
+ */
5
+ export interface LanguageMetadata {
6
+ /** 语言唯一标识 */
7
+ id: string;
8
+ /** 显示名称 */
9
+ name: string;
10
+ /** Monaco Editor 语言 ID */
11
+ monacoId: string;
12
+ /** 图标 emoji(可选) */
13
+ icon?: string;
14
+ /** 文件扩展名列表 */
15
+ extensions: string[];
16
+ /**
17
+ * 默认代码模板(可选,用于向后兼容)
18
+ * 当外部未提供题目配置时使用
19
+ */
20
+ fallbackTemplate?: string;
21
+ /**
22
+ * 是否可运行
23
+ * 标记该语言是否支持代码执行
24
+ */
25
+ canRun?: boolean;
26
+ }
27
+ /**
28
+ * 语言配置(包含运行时信息)
29
+ * 合并了静态元数据和动态配置后的完整语言配置
30
+ */
31
+ export interface LanguageConfig extends LanguageMetadata {
32
+ /** 运行方式类型 */
33
+ runnerType?: "browser" | "wasm" | "remote";
34
+ /** 当前使用的代码模板(运行时确定) */
35
+ currentTemplate?: string;
36
+ }
37
+ //# sourceMappingURL=language.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"language.d.ts","sourceRoot":"","sources":["../../src/types/language.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,aAAa;IACb,EAAE,EAAE,MAAM,CAAC;IAEX,WAAW;IACX,IAAI,EAAE,MAAM,CAAC;IAEb,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IAEjB,mBAAmB;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,cAAc;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;IAErB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAe,SAAQ,gBAAgB;IACtD,aAAa;IACb,UAAU,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IAE3C,uBAAuB;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B"}
@@ -0,0 +1,75 @@
1
+ import { UITestCase } from './index';
2
+
3
+ /**
4
+ * 题目难度级别
5
+ */
6
+ export type QuestionDifficulty = "easy" | "medium" | "hard";
7
+ /**
8
+ * 题目配置
9
+ * 由外部调用者传入,包含题目信息、语言限制、代码模板等
10
+ */
11
+ export interface QuestionConfig {
12
+ /** 题目标题 */
13
+ title?: string;
14
+ /** 题目描述(支持 HTML) */
15
+ description?: string;
16
+ /** 题目描述 Markdown(可选) */
17
+ descriptionMarkdown?: string;
18
+ /** 题目难度(可选) */
19
+ difficulty?: QuestionDifficulty;
20
+ /**
21
+ * 支持的语言 ID 列表(可选)
22
+ * 如果不传,则显示所有语言
23
+ * @example ["python", "java", "cpp"]
24
+ */
25
+ supportedLanguages?: string[];
26
+ /**
27
+ * 每种语言的代码模板
28
+ * key: 语言 ID
29
+ * value: 代码模板字符串
30
+ *
31
+ * @example
32
+ * {
33
+ * python: "def twoSum(nums, target):\n pass",
34
+ * java: "class Solution { ... }"
35
+ * }
36
+ */
37
+ languageTemplates: Record<string, string>;
38
+ /** 默认选中的语言(可选) */
39
+ defaultLanguage?: string;
40
+ /** 测试用例列表(可选) */
41
+ testCases?: UITestCase[];
42
+ /**
43
+ * 题目函数结构(用于根据参数名生成输入框)
44
+ */
45
+ functionStructure?: {
46
+ args: Array<{
47
+ name: string;
48
+ type?: string;
49
+ }>;
50
+ returnType?: string;
51
+ };
52
+ }
53
+ /**
54
+ * Markdown 题目配置(用于左侧题目区的编辑 + 预览)
55
+ */
56
+ export interface QuestionMarkdownOptions {
57
+ /** 初始内容 */
58
+ value?: string;
59
+ /** 是否显示编辑区(默认 true) */
60
+ showEditor?: boolean;
61
+ /** 是否可编辑(默认 true) */
62
+ editable?: boolean;
63
+ /** 是否显示预览区(默认 true) */
64
+ showPreview?: boolean;
65
+ /** 编辑区占位文案 */
66
+ placeholder?: string;
67
+ /** 内容变化回调 */
68
+ onChange?: (value: string) => void;
69
+ }
70
+ /**
71
+ * 语言模板映射
72
+ * 简化版配置,只包含语言到模板的映射
73
+ */
74
+ export type LanguageTemplates = Record<string, string>;
75
+ //# sourceMappingURL=question.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question.d.ts","sourceRoot":"","sources":["../../src/types/question.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE5D;;;GAGG;AACH,MAAM,WAAW,cAAc;IAG7B,WAAW;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,oBAAoB;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,wBAAwB;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,eAAe;IACf,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAIhC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE9B;;;;;;;;;;OAUG;IACH,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE1C,kBAAkB;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IAIzB,iBAAiB;IACjB,SAAS,CAAC,EAAE,UAAU,EAAE,CAAC;IAIzB;;OAEG;IACH,iBAAiB,CAAC,EAAE;QAClB,IAAI,EAAE,KAAK,CAAC;YACV,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,CAAC,EAAE,MAAM,CAAC;SACf,CAAC,CAAC;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,WAAW;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,uBAAuB;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,uBAAuB;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,cAAc;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,aAAa;IACb,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Monaco Editor Loader configuration
3
+ */
4
+ export declare function loadMonaco(): Promise<any>;
5
+ /**
6
+ * 防抖函数
7
+ */
8
+ export declare function debounce(func: Function, wait: number): (this: any, ...args: any[]) => void;
9
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/utils/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,CAoDzC;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,IAElC,MAAM,GAAG,EAAE,GAAG,MAAM,GAAG,EAAE,UAM3C"}
@@ -0,0 +1,2 @@
1
+ export declare function renderMarkdown(markdown: string): string;
2
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/utils/markdown.ts"],"names":[],"mappings":"AAsBA,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkEvD"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "smart-code-editor",
3
+ "version": "1.0.0",
4
+ "description": "智能代码编辑器 - 支持多语言、语法高亮、代码运行,可在 Vue2/3、React、原生 JS 中使用",
5
+ "main": "lib/index.cjs",
6
+ "module": "lib/index.js",
7
+ "types": "lib/index.d.ts",
8
+ "type": "module",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./lib/index.d.ts",
12
+ "import": "./lib/index.js",
13
+ "require": "./lib/index.cjs",
14
+ "default": "./lib/index.umd.cjs"
15
+ }
16
+ },
17
+ "browser": "./lib/index.umd.cjs",
18
+ "author": "haichao_kk",
19
+ "license": "ISC",
20
+ "private": false,
21
+ "files": [
22
+ "lib",
23
+ "src",
24
+ "README.md"
25
+ ],
26
+ "scripts": {
27
+ "dev": "vite --config vite.dev.config.ts",
28
+ "build": "vite build",
29
+ "test": "echo \"Error: no test specified\" && exit 1"
30
+ },
31
+ "keywords": [
32
+ "code-editor",
33
+ "monaco-editor",
34
+ "online-ide",
35
+ "code-runner",
36
+ "vue",
37
+ "react",
38
+ "在线编辑器",
39
+ "代码编辑器",
40
+ "syntax-highlighting",
41
+ "智能提示"
42
+ ],
43
+ "publishConfig": {
44
+ "access": "public",
45
+ "registry": "https://registry.npmjs.org/"
46
+ },
47
+ "dependencies": {
48
+ "marked": "^17.0.1",
49
+ "monaco-editor": "^0.45.0",
50
+ "split.js": "^1.6.5"
51
+ },
52
+ "devDependencies": {
53
+ "@types/node": "^20.0.0",
54
+ "@vitejs/plugin-vue": "^5.0.0",
55
+ "typescript": "^5.3.0",
56
+ "vite": "^5.0.0",
57
+ "vite-plugin-dts": "^3.7.0",
58
+ "vue": "^3.4.0"
59
+ },
60
+ "peerDependencies": {
61
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
62
+ "vue": "^2.7.0 || ^3.3.0"
63
+ },
64
+ "peerDependenciesMeta": {
65
+ "vue": {
66
+ "optional": true
67
+ },
68
+ "react": {
69
+ "optional": true
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,7 @@
1
+ // 原生 JS 直接导出核心类,无需额外封装
2
+ export { SmartCodeEditor } from "../../core/SmartCodeEditor";
3
+ export type {
4
+ SmartCodeEditorOptions,
5
+ RunResult,
6
+ LanguageConfig,
7
+ } from "../../types";