mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 09:23:52 -05:00
something
This commit is contained in:
222
package-lock.json
generated
222
package-lock.json
generated
@@ -15,7 +15,17 @@
|
||||
"@aws-sdk/client-sqs": "^3.828.0",
|
||||
"@aws-sdk/client-ssm": "^3.828.0",
|
||||
"@aws-sdk/credential-providers": "^3.828.0",
|
||||
"@codemirror/autocomplete": "^6.18.6",
|
||||
"@codemirror/commands": "^6.8.1",
|
||||
"@codemirror/lang-cpp": "^6.0.3",
|
||||
"@codemirror/lang-go": "^6.0.1",
|
||||
"@codemirror/lang-java": "^6.0.2",
|
||||
"@codemirror/lang-javascript": "^6.2.4",
|
||||
"@codemirror/lang-python": "^6.2.1",
|
||||
"@codemirror/lang-rust": "^6.0.2",
|
||||
"@codemirror/language": "^6.11.2",
|
||||
"@codemirror/lint": "^6.8.5",
|
||||
"@codemirror/search": "^6.5.11",
|
||||
"@codemirror/state": "^6.5.2",
|
||||
"@codemirror/view": "^6.38.0",
|
||||
"@flatten-js/interval-tree": "^1.1.3",
|
||||
@@ -1542,6 +1552,28 @@
|
||||
"node": ">=14.21.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/autocomplete": {
|
||||
"version": "6.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz",
|
||||
"integrity": "sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.17.0",
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/commands": {
|
||||
"version": "6.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.1.tgz",
|
||||
"integrity": "sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.4.0",
|
||||
"@codemirror/view": "^6.27.0",
|
||||
"@lezer/common": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-cpp": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-cpp/-/lang-cpp-6.0.3.tgz",
|
||||
@@ -1551,6 +1583,62 @@
|
||||
"@lezer/cpp": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-go": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-go/-/lang-go-6.0.1.tgz",
|
||||
"integrity": "sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.6.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.0.0",
|
||||
"@lezer/go": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-java": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-java/-/lang-java-6.0.2.tgz",
|
||||
"integrity": "sha512-m5Nt1mQ/cznJY7tMfQTJchmrjdjQ71IDs+55d1GAa8DGaB8JXWsVCkVT284C3RTASaY43YknrK2X3hPO/J3MOQ==",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@lezer/java": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-javascript": {
|
||||
"version": "6.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.4.tgz",
|
||||
"integrity": "sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.6.0",
|
||||
"@codemirror/lint": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.17.0",
|
||||
"@lezer/common": "^1.0.0",
|
||||
"@lezer/javascript": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-python": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.2.1.tgz",
|
||||
"integrity": "sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.3.2",
|
||||
"@codemirror/language": "^6.8.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.2.1",
|
||||
"@lezer/python": "^1.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-rust": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-rust/-/lang-rust-6.0.2.tgz",
|
||||
"integrity": "sha512-EZaGjCUegtiU7kSMvOfEZpaCReowEf3yNidYu7+vfuGTm9ow4mthAparY5hisJqOHmJowVH3Upu+eJlUji6qqA==",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@lezer/rust": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/language": {
|
||||
"version": "6.11.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.2.tgz",
|
||||
@@ -1564,10 +1652,25 @@
|
||||
"style-mod": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/language/node_modules/@lezer/common": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
|
||||
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA=="
|
||||
"node_modules/@codemirror/lint": {
|
||||
"version": "6.8.5",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.5.tgz",
|
||||
"integrity": "sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.35.0",
|
||||
"crelt": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/search": {
|
||||
"version": "6.5.11",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.11.tgz",
|
||||
"integrity": "sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
"crelt": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/state": {
|
||||
"version": "6.5.2",
|
||||
@@ -2321,6 +2424,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
|
||||
"integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w=="
|
||||
},
|
||||
"node_modules/@lezer/common": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
|
||||
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA=="
|
||||
},
|
||||
"node_modules/@lezer/cpp": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/cpp/-/cpp-1.1.3.tgz",
|
||||
@@ -2331,10 +2439,15 @@
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/cpp/node_modules/@lezer/common": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
|
||||
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA=="
|
||||
"node_modules/@lezer/go": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/go/-/go-1.0.1.tgz",
|
||||
"integrity": "sha512-xToRsYxwsgJNHTgNdStpcvmbVuKxTapV0dM0wey1geMMRc9aggoVyKgzYp41D2/vVOx+Ii4hmE206kvxIXBVXQ==",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/highlight": {
|
||||
"version": "1.2.1",
|
||||
@@ -2344,10 +2457,25 @@
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/highlight/node_modules/@lezer/common": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
|
||||
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA=="
|
||||
"node_modules/@lezer/java": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/java/-/java-1.1.3.tgz",
|
||||
"integrity": "sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw==",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/javascript": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.1.tgz",
|
||||
"integrity": "sha512-ATOImjeVJuvgm3JQ/bpo2Tmv55HSScE2MTPnKRMRIPx2cLhHGyX2VnqpHhtIV1tVzIjZDbcWQm+NCTF40ggZVw==",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.1.3",
|
||||
"@lezer/lr": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/lr": {
|
||||
"version": "1.4.2",
|
||||
@@ -2357,10 +2485,25 @@
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/lr/node_modules/@lezer/common": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
|
||||
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA=="
|
||||
"node_modules/@lezer/python": {
|
||||
"version": "1.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.18.tgz",
|
||||
"integrity": "sha512-31FiUrU7z9+d/ElGQLJFXl+dKOdx0jALlP3KEOsGTex8mvj+SoE1FgItcHWK/axkxCHGUSpqIHt6JAWfWu9Rhg==",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/rust": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/rust/-/rust-1.0.2.tgz",
|
||||
"integrity": "sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@marijn/find-cluster-break": {
|
||||
"version": "1.0.2",
|
||||
@@ -6378,53 +6521,6 @@
|
||||
"@codemirror/view": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/codemirror/node_modules/@codemirror/autocomplete": {
|
||||
"version": "6.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz",
|
||||
"integrity": "sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.17.0",
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/codemirror/node_modules/@codemirror/commands": {
|
||||
"version": "6.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.1.tgz",
|
||||
"integrity": "sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.4.0",
|
||||
"@codemirror/view": "^6.27.0",
|
||||
"@lezer/common": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/codemirror/node_modules/@codemirror/lint": {
|
||||
"version": "6.8.5",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.5.tgz",
|
||||
"integrity": "sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.35.0",
|
||||
"crelt": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/codemirror/node_modules/@codemirror/search": {
|
||||
"version": "6.5.11",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.11.tgz",
|
||||
"integrity": "sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
"crelt": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/codemirror/node_modules/@lezer/common": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
|
||||
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA=="
|
||||
},
|
||||
"node_modules/color": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
|
||||
|
||||
10
package.json
10
package.json
@@ -24,7 +24,17 @@
|
||||
"@aws-sdk/client-sqs": "^3.828.0",
|
||||
"@aws-sdk/client-ssm": "^3.828.0",
|
||||
"@aws-sdk/credential-providers": "^3.828.0",
|
||||
"@codemirror/autocomplete": "^6.18.6",
|
||||
"@codemirror/commands": "^6.8.1",
|
||||
"@codemirror/lang-cpp": "^6.0.3",
|
||||
"@codemirror/lang-go": "^6.0.1",
|
||||
"@codemirror/lang-java": "^6.0.2",
|
||||
"@codemirror/lang-javascript": "^6.2.4",
|
||||
"@codemirror/lang-python": "^6.2.1",
|
||||
"@codemirror/lang-rust": "^6.0.2",
|
||||
"@codemirror/language": "^6.11.2",
|
||||
"@codemirror/lint": "^6.8.5",
|
||||
"@codemirror/search": "^6.5.11",
|
||||
"@codemirror/state": "^6.5.2",
|
||||
"@codemirror/view": "^6.38.0",
|
||||
"@flatten-js/interval-tree": "^1.1.3",
|
||||
|
||||
261
static/codemirror-mobile-editor.ts
Normal file
261
static/codemirror-mobile-editor.ts
Normal file
@@ -0,0 +1,261 @@
|
||||
// CodeMirror 6 implementation for mobile devices in Compiler Explorer
|
||||
import {EditorView, basicSetup} from 'codemirror';
|
||||
import {EditorState, Compartment} from '@codemirror/state';
|
||||
import {cpp} from '@codemirror/lang-cpp';
|
||||
import {javascript} from '@codemirror/lang-javascript';
|
||||
import {python} from '@codemirror/lang-python';
|
||||
import {rust} from '@codemirror/lang-rust';
|
||||
import {go} from '@codemirror/lang-go';
|
||||
import {java} from '@codemirror/lang-java';
|
||||
import {Diagnostic, linter, lintGutter} from '@codemirror/lint';
|
||||
|
||||
import {ICompilerExplorerEditor, CompilerError, EditorOptions} from './editor-abstraction';
|
||||
|
||||
interface LanguageExtension {
|
||||
name: string;
|
||||
extension: () => any;
|
||||
}
|
||||
|
||||
// Language mappings for CodeMirror 6
|
||||
const LANGUAGE_EXTENSIONS: Record<string, LanguageExtension> = {
|
||||
'cpp': {name: 'C++', extension: cpp},
|
||||
'c': {name: 'C', extension: cpp}, // Use C++ for C (close enough)
|
||||
'cxx': {name: 'C++', extension: cpp},
|
||||
'cc': {name: 'C++', extension: cpp},
|
||||
'javascript': {name: 'JavaScript', extension: javascript},
|
||||
'js': {name: 'JavaScript', extension: javascript},
|
||||
'typescript': {name: 'TypeScript', extension: javascript}, // Use JS for TS
|
||||
'ts': {name: 'TypeScript', extension: javascript},
|
||||
'python': {name: 'Python', extension: python},
|
||||
'py': {name: 'Python', extension: python},
|
||||
'rust': {name: 'Rust', extension: rust},
|
||||
'rs': {name: 'Rust', extension: rust},
|
||||
'go': {name: 'Go', extension: go},
|
||||
'java': {name: 'Java', extension: java},
|
||||
};
|
||||
|
||||
export class CodeMirrorMobileEditor implements ICompilerExplorerEditor {
|
||||
private view: EditorView;
|
||||
private container: HTMLElement;
|
||||
private languageCompartment: Compartment;
|
||||
private lintCompartment: Compartment;
|
||||
private currentLanguage: string;
|
||||
private changeCallbacks: (() => void)[] = [];
|
||||
private disposed = false;
|
||||
private currentErrors: CompilerError[] = [];
|
||||
|
||||
constructor(container: HTMLElement, options: EditorOptions = {}) {
|
||||
this.container = container;
|
||||
this.currentLanguage = options.language || 'cpp';
|
||||
|
||||
// Create compartments for dynamic reconfiguration
|
||||
this.languageCompartment = new Compartment();
|
||||
this.lintCompartment = new Compartment();
|
||||
|
||||
// Create initial state
|
||||
const initialState = EditorState.create({
|
||||
doc: '',
|
||||
extensions: [
|
||||
basicSetup,
|
||||
this.languageCompartment.of(this.getLanguageExtension(this.currentLanguage)),
|
||||
this.lintCompartment.of([]),
|
||||
EditorView.updateListener.of(this.createUpdateListener()),
|
||||
EditorView.theme({
|
||||
'&': {
|
||||
fontSize: options.fontSize ? `${options.fontSize}px` : '14px',
|
||||
height: '100%',
|
||||
},
|
||||
'.cm-content': {
|
||||
padding: '10px',
|
||||
fontFamily: 'Monaco, Menlo, "Ubuntu Mono", monospace',
|
||||
minHeight: '200px',
|
||||
},
|
||||
'.cm-focused': {
|
||||
outline: 'none',
|
||||
},
|
||||
'.cm-editor': {
|
||||
height: '100%',
|
||||
},
|
||||
'.cm-scroller': {
|
||||
fontFamily: 'Monaco, Menlo, "Ubuntu Mono", monospace',
|
||||
},
|
||||
// Error styling
|
||||
'.cm-diagnostic-error': {
|
||||
borderLeft: '3px solid #ff5555',
|
||||
backgroundColor: 'rgba(255, 85, 85, 0.1)',
|
||||
},
|
||||
'.cm-diagnostic-warning': {
|
||||
borderLeft: '3px solid #ffaa00',
|
||||
backgroundColor: 'rgba(255, 170, 0, 0.1)',
|
||||
},
|
||||
'.cm-diagnostic-info': {
|
||||
borderLeft: '3px solid #5555ff',
|
||||
backgroundColor: 'rgba(85, 85, 255, 0.1)',
|
||||
},
|
||||
}),
|
||||
// Enable readonly if specified
|
||||
...(options.readOnly ? [EditorState.readOnly.of(true)] : []),
|
||||
],
|
||||
});
|
||||
|
||||
// Create the editor view
|
||||
this.view = new EditorView({
|
||||
state: initialState,
|
||||
parent: container,
|
||||
});
|
||||
|
||||
console.log('CodeMirrorMobileEditor created with language:', this.currentLanguage);
|
||||
}
|
||||
|
||||
private getLanguageExtension(languageId: string): any {
|
||||
const langConfig = LANGUAGE_EXTENSIONS[languageId.toLowerCase()];
|
||||
if (langConfig) {
|
||||
return langConfig.extension();
|
||||
}
|
||||
// Default to C++ if language not found
|
||||
return cpp();
|
||||
}
|
||||
|
||||
private createUpdateListener() {
|
||||
return (update: any) => {
|
||||
if (update.docChanged) {
|
||||
// Notify change callbacks
|
||||
this.notifyChange();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private notifyChange(): void {
|
||||
if (this.disposed) return;
|
||||
this.changeCallbacks.forEach(callback => {
|
||||
try {
|
||||
callback();
|
||||
} catch (error) {
|
||||
console.error('Error in change callback:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ICompilerExplorerEditor implementation
|
||||
getValue(): string {
|
||||
if (this.disposed) throw new Error('Editor disposed');
|
||||
return this.view.state.doc.toString();
|
||||
}
|
||||
|
||||
setValue(value: string): void {
|
||||
if (this.disposed) throw new Error('Editor disposed');
|
||||
|
||||
const transaction = this.view.state.update({
|
||||
changes: {
|
||||
from: 0,
|
||||
to: this.view.state.doc.length,
|
||||
insert: value,
|
||||
},
|
||||
});
|
||||
|
||||
this.view.dispatch(transaction);
|
||||
}
|
||||
|
||||
setLanguage(language: string): void {
|
||||
if (this.disposed) throw new Error('Editor disposed');
|
||||
|
||||
const normalizedLanguage = language.toLowerCase();
|
||||
if (this.currentLanguage === normalizedLanguage) return;
|
||||
|
||||
this.currentLanguage = normalizedLanguage;
|
||||
|
||||
// Update language extension
|
||||
const languageExtension = this.getLanguageExtension(normalizedLanguage);
|
||||
this.view.dispatch({
|
||||
effects: this.languageCompartment.reconfigure(languageExtension),
|
||||
});
|
||||
|
||||
console.log('CodeMirror language changed to:', normalizedLanguage);
|
||||
}
|
||||
|
||||
setErrors(errors: CompilerError[]): void {
|
||||
if (this.disposed) throw new Error('Editor disposed');
|
||||
|
||||
this.currentErrors = [...errors];
|
||||
|
||||
// Convert CompilerError[] to CodeMirror Diagnostic[]
|
||||
const diagnostics: Diagnostic[] = errors.map(error => {
|
||||
// Convert 1-based line numbers to 0-based positions
|
||||
const line = Math.max(0, error.line - 1);
|
||||
const doc = this.view.state.doc;
|
||||
const lineInfo = doc.line(Math.min(line + 1, doc.lines));
|
||||
const from = lineInfo.from + Math.max(0, error.column - 1);
|
||||
const to = Math.min(from + 1, lineInfo.to); // At least one character
|
||||
|
||||
return {
|
||||
from,
|
||||
to,
|
||||
severity: error.severity,
|
||||
message: error.message,
|
||||
};
|
||||
});
|
||||
|
||||
// Create linter that returns our diagnostics
|
||||
const errorLinter = linter(() => diagnostics);
|
||||
|
||||
// Update lint compartment
|
||||
this.view.dispatch({
|
||||
effects: this.lintCompartment.reconfigure([
|
||||
errorLinter,
|
||||
lintGutter(),
|
||||
]),
|
||||
});
|
||||
}
|
||||
|
||||
onChange(callback: () => void): void {
|
||||
if (this.disposed) throw new Error('Editor disposed');
|
||||
this.changeCallbacks.push(callback);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
if (this.disposed) return;
|
||||
|
||||
this.disposed = true;
|
||||
this.changeCallbacks = [];
|
||||
this.currentErrors = [];
|
||||
|
||||
// Destroy CodeMirror view
|
||||
this.view.destroy();
|
||||
|
||||
// Clear container
|
||||
this.container.innerHTML = '';
|
||||
|
||||
console.log('CodeMirrorMobileEditor disposed');
|
||||
}
|
||||
|
||||
// Additional methods for enhanced functionality
|
||||
focus(): void {
|
||||
if (!this.disposed) {
|
||||
this.view.focus();
|
||||
}
|
||||
}
|
||||
|
||||
layout(): void {
|
||||
// CodeMirror 6 handles layout automatically, but we can force a refresh
|
||||
if (!this.disposed) {
|
||||
this.view.requestMeasure();
|
||||
}
|
||||
}
|
||||
|
||||
getLanguage(): string {
|
||||
return this.currentLanguage;
|
||||
}
|
||||
|
||||
getErrors(): CompilerError[] {
|
||||
return [...this.currentErrors];
|
||||
}
|
||||
|
||||
isDisposed(): boolean {
|
||||
return this.disposed;
|
||||
}
|
||||
|
||||
// Get the underlying CodeMirror view for advanced usage
|
||||
getCodeMirrorView(): EditorView | null {
|
||||
return this.disposed ? null : this.view;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,13 @@
|
||||
// CodeMirror 6 test page entry point
|
||||
import {EditorView} from '@codemirror/view';
|
||||
import {EditorState} from '@codemirror/state';
|
||||
import {syntaxHighlighting, HighlightStyle} from '@codemirror/language';
|
||||
import {tags} from '@lezer/highlight';
|
||||
import {EditorView, basicSetup} from 'codemirror';
|
||||
import {cpp} from '@codemirror/lang-cpp';
|
||||
// import {createEditor, createEditorSync} from './editor-abstraction';
|
||||
import {CodeMirrorMobileEditor} from './codemirror-mobile-editor';
|
||||
|
||||
console.log('CodeMirror test script loaded, imports successful');
|
||||
console.log('EditorView:', EditorView);
|
||||
console.log('EditorState:', EditorState);
|
||||
console.log('C++ language support:', cpp);
|
||||
console.log('C++ language function result:', cpp());
|
||||
console.log('Syntax highlighting:', syntaxHighlighting);
|
||||
console.log('Highlight tags:', tags);
|
||||
console.log('C++ language support:', cpp);
|
||||
console.log('basicSetup:', basicSetup);
|
||||
console.log('cpp:', cpp);
|
||||
|
||||
function initializeCodeMirrorTest() {
|
||||
console.log('CodeMirror 6 test page loaded - DOM ready');
|
||||
@@ -35,141 +30,89 @@ int main() {
|
||||
const cmContainer = document.getElementById('codemirror-editor');
|
||||
if (cmContainer) {
|
||||
try {
|
||||
console.log('Creating CodeMirror editor...');
|
||||
|
||||
const cppExtension = cpp();
|
||||
console.log('C++ extension created:', cppExtension);
|
||||
console.log('C++ extension type:', typeof cppExtension);
|
||||
console.log('C++ extension constructor:', cppExtension.constructor?.name);
|
||||
|
||||
// Create a custom highlight style to avoid version conflicts
|
||||
const customHighlightStyle = HighlightStyle.define([
|
||||
{ tag: tags.comment, color: '#008000' },
|
||||
{ tag: tags.keyword, color: '#0000FF' },
|
||||
{ tag: tags.string, color: '#800080' },
|
||||
{ tag: tags.number, color: '#FF0000' },
|
||||
{ tag: tags.variableName, color: '#000000' },
|
||||
{ tag: tags.typeName, color: '#008080' },
|
||||
{ tag: tags.operator, color: '#000000' },
|
||||
{ tag: tags.bracket, color: '#000000' }
|
||||
]);
|
||||
|
||||
console.log('Custom highlight style created:', customHighlightStyle);
|
||||
|
||||
const highlightExtension = syntaxHighlighting(customHighlightStyle);
|
||||
console.log('Highlight extension created:', highlightExtension);
|
||||
|
||||
const extensions = [
|
||||
cppExtension, // Add C++ language support first
|
||||
highlightExtension, // Add syntax highlighting
|
||||
EditorView.lineWrapping,
|
||||
EditorView.theme({
|
||||
'&': { height: '250px', border: '1px solid #ddd' },
|
||||
'.cm-content': { padding: '10px', fontFamily: 'monospace', fontSize: '14px' },
|
||||
'.cm-focused': { outline: 'none' }
|
||||
}),
|
||||
EditorView.updateListener.of(update => {
|
||||
if (update.docChanged) {
|
||||
console.log('CodeMirror content changed');
|
||||
const outputEl = document.getElementById('cm-output');
|
||||
if (outputEl) {
|
||||
outputEl.textContent =
|
||||
'Content: ' + view.state.doc.toString().substring(0, 50) + '...';
|
||||
}
|
||||
}
|
||||
})
|
||||
];
|
||||
|
||||
console.log('Extensions array:', extensions);
|
||||
console.log('Extensions length:', extensions.length);
|
||||
extensions.forEach((ext, i) => {
|
||||
console.log(`Extension ${i}:`, ext, typeof ext);
|
||||
});
|
||||
|
||||
const state = EditorState.create({
|
||||
doc: `// CodeMirror 6 Editor (real transaction-based)
|
||||
#include <iostream>
|
||||
// Exact official example
|
||||
new EditorView({
|
||||
parent: cmContainer,
|
||||
doc: `#include <iostream>
|
||||
int main() {
|
||||
std::cout << "Hello from CodeMirror 6!" << std::endl;
|
||||
std::cout << "Hello World!" << std::endl;
|
||||
return 0;
|
||||
}`,
|
||||
extensions: extensions
|
||||
extensions: [basicSetup, cpp()]
|
||||
});
|
||||
|
||||
console.log('EditorState created:', state);
|
||||
console.log('State language data:', state.languageDataAt('language', 0));
|
||||
|
||||
const view = new EditorView({
|
||||
state: state,
|
||||
parent: cmContainer
|
||||
});
|
||||
|
||||
console.log('EditorView created:', view);
|
||||
|
||||
// Check if syntax highlighting is working
|
||||
setTimeout(() => {
|
||||
console.log('=== Checking syntax highlighting after render ===');
|
||||
const cmContent = cmContainer.querySelector('.cm-content');
|
||||
if (cmContent) {
|
||||
console.log('CM content element found:', cmContent);
|
||||
const highlightedElements = cmContent.querySelectorAll('[class*="cm-"]');
|
||||
console.log('Highlighted elements found:', highlightedElements.length);
|
||||
Array.from(highlightedElements).forEach((el, i) => {
|
||||
if (i < 5) { // Log first 5 elements
|
||||
console.log(`Highlighted element ${i}:`, el.className, el.textContent);
|
||||
}
|
||||
});
|
||||
|
||||
// Check for specific C++ tokens
|
||||
const includeElements = cmContent.querySelectorAll('[class*="keyword"], [class*="include"]');
|
||||
console.log('Include/keyword elements:', includeElements.length);
|
||||
|
||||
const commentElements = cmContent.querySelectorAll('[class*="comment"]');
|
||||
console.log('Comment elements:', commentElements.length);
|
||||
} else {
|
||||
console.log('CM content element not found');
|
||||
}
|
||||
}, 100);
|
||||
|
||||
// Test the abstraction API
|
||||
const setValueBtn = document.getElementById('test-setValue');
|
||||
if (setValueBtn) {
|
||||
setValueBtn.onclick = () => {
|
||||
view.dispatch({
|
||||
changes: {
|
||||
from: 0,
|
||||
to: view.state.doc.length,
|
||||
insert: 'int main() { return 42; }'
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const getValueBtn = document.getElementById('test-getValue');
|
||||
if (getValueBtn) {
|
||||
getValueBtn.onclick = () => {
|
||||
const content = view.state.doc.toString();
|
||||
const outputEl = document.getElementById('cm-output');
|
||||
if (outputEl) {
|
||||
outputEl.textContent = 'Content: ' + content;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
console.log('CodeMirror 6 editor created successfully');
|
||||
const statusEl = document.getElementById('cm-status');
|
||||
if (statusEl) {
|
||||
statusEl.textContent = 'CodeMirror 6 loaded successfully with C++ syntax highlighting!';
|
||||
statusEl.style.color = 'green';
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to create CodeMirror editor:', error);
|
||||
const statusEl = document.getElementById('cm-status');
|
||||
if (statusEl) {
|
||||
statusEl.textContent = 'CodeMirror 6 failed to load: ' + (error as Error).message;
|
||||
statusEl.style.color = 'red';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test 3: CodeMirror Mobile Editor Class
|
||||
const mobileContainer = document.getElementById('mobile-editor');
|
||||
if (mobileContainer) {
|
||||
try {
|
||||
console.log('Creating CodeMirrorMobileEditor...');
|
||||
|
||||
const mobileEditor = new CodeMirrorMobileEditor(mobileContainer, {
|
||||
language: 'cpp',
|
||||
fontSize: 14,
|
||||
});
|
||||
|
||||
mobileEditor.setValue(`// CodeMirror Mobile Editor Test
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
int main() {
|
||||
std::vector<int> numbers = {1, 2, 3, 4, 5};
|
||||
|
||||
for (const auto& num : numbers) {
|
||||
std::cout << "Number: " << num << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}`);
|
||||
|
||||
// Test language switching
|
||||
setTimeout(() => {
|
||||
console.log('Testing language switch to JavaScript...');
|
||||
mobileEditor.setLanguage('javascript');
|
||||
mobileEditor.setValue(`// JavaScript test
|
||||
function fibonacci(n) {
|
||||
if (n <= 1) return n;
|
||||
return fibonacci(n - 1) + fibonacci(n - 2);
|
||||
}
|
||||
|
||||
console.log('Fibonacci(10):', fibonacci(10));`);
|
||||
}, 2000);
|
||||
|
||||
// Test error display
|
||||
setTimeout(() => {
|
||||
console.log('Testing error display...');
|
||||
mobileEditor.setErrors([
|
||||
{
|
||||
line: 3,
|
||||
column: 10,
|
||||
message: 'Example compilation error',
|
||||
severity: 'error'
|
||||
},
|
||||
{
|
||||
line: 8,
|
||||
column: 5,
|
||||
message: 'Example warning',
|
||||
severity: 'warning'
|
||||
}
|
||||
]);
|
||||
}, 4000);
|
||||
|
||||
// Test change callback
|
||||
mobileEditor.onChange(() => {
|
||||
console.log('Mobile editor content changed, new length:', mobileEditor.getValue().length);
|
||||
});
|
||||
|
||||
console.log('CodeMirrorMobileEditor created successfully');
|
||||
} catch (error) {
|
||||
console.error('Failed to create CodeMirrorMobileEditor:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,8 +94,25 @@ export class MockEditor implements ICompilerExplorerEditor {
|
||||
}
|
||||
|
||||
// Factory function for creating editors
|
||||
export function createEditor(container: HTMLElement, options: EditorOptions): ICompilerExplorerEditor {
|
||||
// For now, just return mock editor for testing
|
||||
// Later this will detect mobile and return appropriate implementation
|
||||
export async function createEditor(container: HTMLElement, options: EditorOptions): Promise<ICompilerExplorerEditor> {
|
||||
// Detect mobile/touch devices
|
||||
const isMobile = window.compilerExplorerOptions?.mobileViewer ||
|
||||
'ontouchstart' in window ||
|
||||
navigator.maxTouchPoints > 0;
|
||||
|
||||
if (isMobile) {
|
||||
// Dynamic import for CodeMirror to avoid loading on desktop
|
||||
const module = await import('./codemirror-mobile-editor');
|
||||
return new module.CodeMirrorMobileEditor(container, options);
|
||||
} else {
|
||||
// Return mock editor for desktop (later this will be Monaco wrapper)
|
||||
return new MockEditor();
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronous factory for immediate creation (uses mock for now)
|
||||
export function createEditorSync(container: HTMLElement, options: EditorOptions): ICompilerExplorerEditor {
|
||||
// For now, return mock editor for testing
|
||||
// This will be replaced with proper sync creation once we integrate
|
||||
return new MockEditor();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,12 @@ block content
|
||||
h3 CodeMirror 6 Editor (Transaction-based)
|
||||
#codemirror-editor
|
||||
|
||||
.row.mt-4
|
||||
.col-12
|
||||
h3 CodeMirror Mobile Editor Class (with Language Support)
|
||||
#mobile-editor
|
||||
p.small This tests the full CodeMirrorMobileEditor class with language switching, error display, and change detection.
|
||||
|
||||
.row.mt-4
|
||||
.col-12
|
||||
h3 CodeMirror 6 Status
|
||||
|
||||
Reference in New Issue
Block a user