Merge pull request #72 from Heavrnl/feature/codemirror
Feature/codemirror
This commit is contained in:
Generated
+484
@@ -103,6 +103,255 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.17.0",
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-cpp": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-cpp/-/lang-cpp-6.0.2.tgz",
|
||||
"integrity": "sha512-6oYEYUKHvrnacXxWxYa6t4puTlbN3dgV662BDfSH8+MfjQjVmP697/KYTDOqpxgerkvoNm7q5wlFMBeX8ZMocg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@lezer/cpp": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-css": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz",
|
||||
"integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.0.2",
|
||||
"@lezer/css": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"license": "MIT",
|
||||
"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-html": {
|
||||
"version": "6.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz",
|
||||
"integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/lang-css": "^6.0.0",
|
||||
"@codemirror/lang-javascript": "^6.0.0",
|
||||
"@codemirror/language": "^6.4.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.17.0",
|
||||
"@lezer/common": "^1.0.0",
|
||||
"@lezer/css": "^1.1.0",
|
||||
"@lezer/html": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-java": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-java/-/lang-java-6.0.1.tgz",
|
||||
"integrity": "sha512-OOnmhH67h97jHzCuFaIEspbmsT98fNdhVhmA3zCxW0cn7l8rChDhZtwiwJ/JOKXgfm4J+ELxQihxaI7bj7mJRg==",
|
||||
"license": "MIT",
|
||||
"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==",
|
||||
"license": "MIT",
|
||||
"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-json": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz",
|
||||
"integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@lezer/json": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-markdown": {
|
||||
"version": "6.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.3.2.tgz",
|
||||
"integrity": "sha512-c/5MYinGbFxYl4itE9q/rgN/sMTjOr8XL5OWnC+EaRMLfCbVUmmubTJfdgpfcSS2SCaT7b+Q+xi3l6CgoE+BsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.7.1",
|
||||
"@codemirror/lang-html": "^6.0.0",
|
||||
"@codemirror/language": "^6.3.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
"@lezer/common": "^1.2.1",
|
||||
"@lezer/markdown": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-php": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-php/-/lang-php-6.0.1.tgz",
|
||||
"integrity": "sha512-ublojMdw/PNWa7qdN5TMsjmqkNuTBD3k6ndZ4Z0S25SBAiweFGyY68AS3xNcIOlb6DDFDvKlinLQ40vSLqf8xA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/lang-html": "^6.0.0",
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.0.0",
|
||||
"@lezer/php": "^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==",
|
||||
"license": "MIT",
|
||||
"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.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-rust/-/lang-rust-6.0.1.tgz",
|
||||
"integrity": "sha512-344EMWFBzWArHWdZn/NcgkwMvZIWUR1GEBdwG8FEp++6o6vT6KL9V7vGs2ONsKxxFUPXKI0SPcWhyYyl2zPYxQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@lezer/rust": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-sql": {
|
||||
"version": "6.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.9.0.tgz",
|
||||
"integrity": "sha512-xmtpWqKSgum1B1J3Ro6rf7nuPqf2+kJQg5SjrofCAcyCThOe0ihSktSoXfXuhQBnwx1QbmreBbLJM5Jru6zitg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-xml": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz",
|
||||
"integrity": "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.4.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
"@lezer/common": "^1.0.0",
|
||||
"@lezer/xml": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-yaml": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.2.tgz",
|
||||
"integrity": "sha512-dxrfG8w5Ce/QbT7YID7mWZFKhdhsaTNOYjOkSIMt1qmC4VQnXSDSYVHHHn8k6kJUfIhtLo8t1JJgltlxWdsITw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.2.0",
|
||||
"@lezer/lr": "^1.0.0",
|
||||
"@lezer/yaml": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/language": {
|
||||
"version": "6.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.1.tgz",
|
||||
"integrity": "sha512-5kS1U7emOGV84vxC+ruBty5sUgcD0te6dyupyRVG2zaSjhTDM73LhVKUtVwiqSe6QwmEoA4SCiU8AKPFyumAWQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.23.0",
|
||||
"@lezer/common": "^1.1.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0",
|
||||
"style-mod": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/legacy-modes": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.5.1.tgz",
|
||||
"integrity": "sha512-DJYQQ00N1/KdESpZV7jg9hafof/iBNp9h7TYo1SLMk86TWl9uDsVdho2dzd81K+v4retmK6mdC7WpuOQDytQqw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lint": {
|
||||
"version": "6.8.5",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.5.tgz",
|
||||
"integrity": "sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.35.0",
|
||||
"crelt": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/state": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz",
|
||||
"integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@marijn/find-cluster-break": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/view": {
|
||||
"version": "6.37.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.37.1.tgz",
|
||||
"integrity": "sha512-Qy4CAUwngy/VQkEz0XzMKVRcckQuqLYWKqVpDDDghBe5FSXSqfVrJn49nw3ePZHxRUz4nRmb05Lgi+9csWo4eg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.5.0",
|
||||
"crelt": "^1.0.6",
|
||||
"style-mod": "^4.1.0",
|
||||
"w3c-keyname": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@cspotcode/source-map-support": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||
@@ -797,6 +1046,172 @@
|
||||
"integrity": "sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"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==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@lezer/cpp": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/cpp/-/cpp-1.1.3.tgz",
|
||||
"integrity": "sha512-ykYvuFQKGsRi6IcE+/hCSGUhb/I4WPjd3ELhEblm2wS2cOznDFzO+ubK2c+ioysOnlZ3EduV+MVQFCPzAIoY3w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/css": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.2.1.tgz",
|
||||
"integrity": "sha512-2F5tOqzKEKbCUNraIXc0f6HKeyKlmMWJnBB0i4XW6dJgssrZO/YlZ2pY5xgyqDleqqhiNJ3dQhbrV2aClZQMvg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/highlight": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz",
|
||||
"integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/html": {
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.10.tgz",
|
||||
"integrity": "sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"license": "MIT",
|
||||
"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==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.1.3",
|
||||
"@lezer/lr": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/json": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz",
|
||||
"integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/lr": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz",
|
||||
"integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/markdown": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.4.3.tgz",
|
||||
"integrity": "sha512-kfw+2uMrQ/wy/+ONfrH83OkdFNM0ye5Xq96cLlaCy7h5UT9FO54DU4oRoIc0CSBh5NWmWuiIJA7NGLMJbQ+Oxg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0",
|
||||
"@lezer/highlight": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/php": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/php/-/php-1.0.2.tgz",
|
||||
"integrity": "sha512-GN7BnqtGRpFyeoKSEqxvGvhJQiI4zkgmYnDk/JIyc7H7Ifc1tkPnUn/R2R8meH3h/aBf5rzjvU8ZQoyiNDtDrA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"license": "MIT",
|
||||
"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==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/xml": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.6.tgz",
|
||||
"integrity": "sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/yaml": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.3.tgz",
|
||||
"integrity": "sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
|
||||
@@ -833,6 +1248,12 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@marijn/find-cluster-break": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
|
||||
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@nexus-terminal/backend": {
|
||||
"resolved": "packages/backend",
|
||||
"link": true
|
||||
@@ -2032,6 +2453,37 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-vscode": {
|
||||
"version": "4.23.12",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-vscode/-/codemirror-theme-vscode-4.23.12.tgz",
|
||||
"integrity": "sha512-ePBaUQiixrpmSoZJWCGXUStKmcM8G0VBv3UqwPR+kNGBjqDife76Gbhv77izSeEI3zRPzL+683BOdclkvWnsMg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.23.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-themes": {
|
||||
"version": "4.23.12",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.23.12.tgz",
|
||||
"integrity": "sha512-8etEByfS9yttFZW0rcWhdZc7/JXJKRWlU5lHmJCI3GydZNGCzydNA+HtK9nWKpJUndVc58Q2sqSC5OIcwq8y6A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@codemirror/language": ">=6.0.0",
|
||||
"@codemirror/state": ">=6.0.0",
|
||||
"@codemirror/view": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitejs/plugin-vue": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.6.2.tgz",
|
||||
@@ -3760,6 +4212,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/crelt": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
||||
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cross-env": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
|
||||
@@ -8098,6 +8556,12 @@
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/style-mod": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
|
||||
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/superjson": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz",
|
||||
@@ -9016,6 +9480,12 @@
|
||||
"vue": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/w3c-keyname": {
|
||||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
@@ -9431,10 +9901,24 @@
|
||||
"name": "@nexus-terminal/frontend",
|
||||
"version": "0.7.13",
|
||||
"dependencies": {
|
||||
"@codemirror/lang-cpp": "^6.0.2",
|
||||
"@codemirror/lang-go": "^6.0.1",
|
||||
"@codemirror/lang-java": "^6.0.1",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@codemirror/lang-markdown": "^6.3.2",
|
||||
"@codemirror/lang-php": "^6.0.1",
|
||||
"@codemirror/lang-python": "^6.2.1",
|
||||
"@codemirror/lang-rust": "^6.0.1",
|
||||
"@codemirror/lang-sql": "^6.9.0",
|
||||
"@codemirror/lang-xml": "^6.1.0",
|
||||
"@codemirror/lang-yaml": "^6.1.2",
|
||||
"@codemirror/legacy-modes": "^6.5.1",
|
||||
"@fortawesome/fontawesome-free": "^6.7.2",
|
||||
"@hcaptcha/vue3-hcaptcha": "^1.3.0",
|
||||
"@lezer/markdown": "^1.4.3",
|
||||
"@simplewebauthn/browser": "^9.0.1",
|
||||
"@tailwindcss/vite": "^4.1.4",
|
||||
"@uiw/codemirror-theme-vscode": "^4.23.12",
|
||||
"@vscode/iconv-lite-umd": "^0.7.0",
|
||||
"@vueuse/core": "^13.1.0",
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
|
||||
@@ -55,6 +55,9 @@ let terminalTextStrokeEnabledFound = false;
|
||||
case 'editorFontSize':
|
||||
settings.editorFontSize = parseInt(row.value, 10);
|
||||
break;
|
||||
case 'mobileEditorFontSize':
|
||||
settings.mobileEditorFontSize = parseInt(row.value, 10);
|
||||
break;
|
||||
case 'terminalBackgroundImage':
|
||||
settings.terminalBackgroundImage = row.value || undefined;
|
||||
break;
|
||||
@@ -122,6 +125,7 @@ case 'terminalTextStrokeEnabled':
|
||||
terminalFontSize: settings.terminalFontSize ?? defaults.terminalFontSize,
|
||||
terminalFontSizeMobile: settings.terminalFontSizeMobile ?? defaults.terminalFontSizeMobile,
|
||||
editorFontSize: settings.editorFontSize ?? defaults.editorFontSize,
|
||||
mobileEditorFontSize: settings.mobileEditorFontSize ?? defaults.mobileEditorFontSize,
|
||||
editorFontFamily: settings.editorFontFamily ?? defaults.editorFontFamily,
|
||||
terminalBackgroundImage: settings.terminalBackgroundImage ?? defaults.terminalBackgroundImage,
|
||||
pageBackgroundImage: settings.pageBackgroundImage ?? defaults.pageBackgroundImage,
|
||||
@@ -172,6 +176,7 @@ const getDefaultAppearanceSettings = (): Omit<AppearanceSettings, '_id'> => {
|
||||
terminalFontSize: 14,
|
||||
terminalFontSizeMobile: 14, // 移动端默认字体大小
|
||||
editorFontSize: 14,
|
||||
mobileEditorFontSize: 16, //移动端编辑器默认字体大小
|
||||
editorFontFamily: 'Consolas, "Noto Sans SC", "Microsoft YaHei"',
|
||||
terminalBackgroundImage: undefined,
|
||||
pageBackgroundImage: undefined,
|
||||
@@ -213,6 +218,7 @@ export const ensureDefaultSettingsExist = async (db: sqlite3.Database): Promise<
|
||||
{ key: 'terminalFontSize', value: defaults.terminalFontSize },
|
||||
{ key: 'terminalFontSizeMobile', value: defaults.terminalFontSizeMobile },
|
||||
{ key: 'editorFontSize', value: defaults.editorFontSize },
|
||||
{ key: 'mobileEditorFontSize', value: defaults.mobileEditorFontSize },
|
||||
{ key: 'editorFontFamily', value: defaults.editorFontFamily },
|
||||
{ key: 'terminalBackgroundImage', value: defaults.terminalBackgroundImage ?? '' }, // 数据库中使用空字符串
|
||||
{ key: 'pageBackgroundImage', value: defaults.pageBackgroundImage ?? '' }, // 数据库中使用空字符串
|
||||
|
||||
@@ -114,6 +114,16 @@ export const updateSettings = async (settingsDto: UpdateAppearanceDto): Promise<
|
||||
settingsDto.editorFontSize = size;
|
||||
}
|
||||
|
||||
// 验证 mobileEditorFontSize (如果提供了)
|
||||
if (settingsDto.mobileEditorFontSize !== undefined && settingsDto.mobileEditorFontSize !== null) {
|
||||
const size = Number(settingsDto.mobileEditorFontSize);
|
||||
if (isNaN(size) || size <= 0) {
|
||||
throw new Error(`无效的移动端编辑器字体大小: ${settingsDto.mobileEditorFontSize}。必须是一个正数。`);
|
||||
}
|
||||
// 确保类型正确传递给仓库层
|
||||
settingsDto.mobileEditorFontSize = size;
|
||||
}
|
||||
|
||||
// 验证 editorFontFamily (如果提供了)
|
||||
if (settingsDto.hasOwnProperty('editorFontFamily')) {
|
||||
if (settingsDto.editorFontFamily === null) {
|
||||
|
||||
@@ -9,10 +9,24 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/lang-cpp": "^6.0.2",
|
||||
"@codemirror/lang-go": "^6.0.1",
|
||||
"@codemirror/lang-java": "^6.0.1",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@codemirror/lang-markdown": "^6.3.2",
|
||||
"@codemirror/lang-php": "^6.0.1",
|
||||
"@codemirror/lang-python": "^6.2.1",
|
||||
"@codemirror/lang-rust": "^6.0.1",
|
||||
"@codemirror/lang-sql": "^6.9.0",
|
||||
"@codemirror/lang-xml": "^6.1.0",
|
||||
"@codemirror/lang-yaml": "^6.1.2",
|
||||
"@codemirror/legacy-modes": "^6.5.1",
|
||||
"@fortawesome/fontawesome-free": "^6.7.2",
|
||||
"@hcaptcha/vue3-hcaptcha": "^1.3.0",
|
||||
"@lezer/markdown": "^1.4.3",
|
||||
"@simplewebauthn/browser": "^9.0.1",
|
||||
"@tailwindcss/vite": "^4.1.4",
|
||||
"@uiw/codemirror-theme-vscode": "^4.23.12",
|
||||
"@vscode/iconv-lite-umd": "^0.7.0",
|
||||
"@vueuse/core": "^13.1.0",
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
<template>
|
||||
<div ref="editorRef" class="codemirror-mobile-editor-container" :style="{ fontSize: currentFontSize + 'px', fontFamily: editorFontFamily }"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeUnmount, watch, shallowRef, computed } from 'vue';
|
||||
import { EditorState, Compartment } from '@codemirror/state';
|
||||
import { useAppearanceStore } from '../stores/appearance.store';
|
||||
import { EditorView, keymap, lineNumbers, highlightActiveLineGutter, highlightActiveLine, drawSelection, dropCursor } from '@codemirror/view';
|
||||
import { syntaxHighlighting, defaultHighlightStyle, indentOnInput, bracketMatching, foldGutter, foldKeymap } from '@codemirror/language';
|
||||
import { vscodeDark } from '@uiw/codemirror-theme-vscode';
|
||||
import { history, historyKeymap, defaultKeymap } from '@codemirror/commands';
|
||||
import { autocompletion, closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';
|
||||
import { highlightSelectionMatches, searchKeymap, openSearchPanel } from '@codemirror/search'; // + Import search functionalities
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
language: {
|
||||
type: String,
|
||||
default: 'plaintext',
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'request-save']);
|
||||
|
||||
const appearanceStore = useAppearanceStore();
|
||||
const editorRef = ref<HTMLDivElement | null>(null);
|
||||
const view = shallowRef<EditorView | null>(null);
|
||||
const languageCompartment = new Compartment();
|
||||
const currentFontSize = ref(appearanceStore.currentMobileEditorFontSize);
|
||||
const MIN_FONT_SIZE = 8;
|
||||
const MAX_FONT_SIZE = 40;
|
||||
let lastPinchDistance = 0;
|
||||
const debounceTimeout = ref<number | null>(null);
|
||||
const DEBOUNCE_DELAY = 500; // 500ms 防抖延迟
|
||||
|
||||
const editorFontFamily = computed(() => appearanceStore.currentEditorFontFamily);
|
||||
|
||||
const getDistance = (touches: TouchList): number => {
|
||||
if (touches.length < 2) return 0;
|
||||
const touch1 = touches[0];
|
||||
const touch2 = touches[1];
|
||||
return Math.sqrt(
|
||||
Math.pow(touch2.pageX - touch1.pageX, 2) +
|
||||
Math.pow(touch2.pageY - touch1.pageY, 2)
|
||||
);
|
||||
};
|
||||
|
||||
const onTouchStart = (event: TouchEvent) => {
|
||||
if (editorRef.value && editorRef.value.contains(event.target as Node)) {
|
||||
if (event.touches.length === 2) {
|
||||
event.preventDefault();
|
||||
lastPinchDistance = getDistance(event.touches);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const debouncedSetMobileEditorFontSize = (size: number) => {
|
||||
if (debounceTimeout.value !== null) {
|
||||
clearTimeout(debounceTimeout.value);
|
||||
}
|
||||
debounceTimeout.value = window.setTimeout(() => {
|
||||
appearanceStore.setMobileEditorFontSize(size);
|
||||
}, DEBOUNCE_DELAY);
|
||||
};
|
||||
|
||||
const onTouchMove = (event: TouchEvent) => {
|
||||
if (editorRef.value && editorRef.value.contains(event.target as Node)) {
|
||||
if (event.touches.length === 2) {
|
||||
event.preventDefault();
|
||||
const newPinchDistance = getDistance(event.touches);
|
||||
if (lastPinchDistance > 0 && newPinchDistance > 0) {
|
||||
const scale = newPinchDistance / lastPinchDistance;
|
||||
let newFontSize = currentFontSize.value * scale;
|
||||
newFontSize = Math.max(MIN_FONT_SIZE, Math.min(MAX_FONT_SIZE, newFontSize));
|
||||
|
||||
if (Math.abs(currentFontSize.value - newFontSize) > 0.1) {
|
||||
currentFontSize.value = newFontSize;
|
||||
debouncedSetMobileEditorFontSize(newFontSize);
|
||||
}
|
||||
}
|
||||
if (newPinchDistance > 0) {
|
||||
lastPinchDistance = newPinchDistance;
|
||||
} else if (event.touches.length === 2) {
|
||||
lastPinchDistance = getDistance(event.touches);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onTouchEnd = (event: TouchEvent) => {
|
||||
if (event.touches.length < 2) {
|
||||
lastPinchDistance = 0;
|
||||
}
|
||||
};
|
||||
const createEditorState = (doc: string, languageExtension: any) => {
|
||||
return EditorState.create({
|
||||
doc,
|
||||
extensions: [
|
||||
languageCompartment.of(languageExtension),
|
||||
vscodeDark,
|
||||
lineNumbers(),
|
||||
history(),
|
||||
highlightActiveLineGutter(),
|
||||
foldGutter(),
|
||||
drawSelection(),
|
||||
dropCursor(),
|
||||
EditorState.allowMultipleSelections.of(true),
|
||||
indentOnInput(),
|
||||
bracketMatching(),
|
||||
highlightActiveLine(),
|
||||
closeBrackets(),
|
||||
autocompletion(),
|
||||
highlightSelectionMatches(),
|
||||
EditorView.updateListener.of((update) => {
|
||||
if (update.docChanged) {
|
||||
emit('update:modelValue', update.state.doc.toString());
|
||||
}
|
||||
}),
|
||||
keymap.of([
|
||||
...closeBracketsKeymap,
|
||||
...defaultKeymap,
|
||||
...historyKeymap,
|
||||
...foldKeymap,
|
||||
...searchKeymap, // + Add search keymap
|
||||
{ key: "Mod-s", run: () => { emit('request-save'); return true; } }
|
||||
]),
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
const getLanguageExtension = async (lang: string) => {
|
||||
if (lang === 'javascript') {
|
||||
const { javascript } = await import('@codemirror/lang-javascript');
|
||||
return javascript();
|
||||
}
|
||||
if (lang === 'css') {
|
||||
try {
|
||||
const cssModule = await import('@codemirror/lang-css');
|
||||
if (cssModule && typeof cssModule.css === 'function') {
|
||||
const cssExtension = cssModule.css();
|
||||
return cssExtension;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
if (lang === 'html') {
|
||||
const { html } = await import('@codemirror/lang-html');
|
||||
return html();
|
||||
}
|
||||
if (lang === 'python') {
|
||||
const { python } = await import('@codemirror/lang-python');
|
||||
return python();
|
||||
}
|
||||
if (lang === 'java') {
|
||||
const { java } = await import('@codemirror/lang-java');
|
||||
return java();
|
||||
}
|
||||
if (lang === 'cpp') {
|
||||
const { cpp } = await import('@codemirror/lang-cpp');
|
||||
return cpp();
|
||||
}
|
||||
if (lang === 'php') {
|
||||
const { php } = await import('@codemirror/lang-php');
|
||||
return php();
|
||||
}
|
||||
if (lang === 'go') {
|
||||
const { go } = await import('@codemirror/lang-go');
|
||||
return go();
|
||||
}
|
||||
if (lang === 'rust') {
|
||||
const { rust } = await import('@codemirror/lang-rust');
|
||||
return rust();
|
||||
}
|
||||
if (lang === 'sql') {
|
||||
const { sql } = await import('@codemirror/lang-sql');
|
||||
return sql();
|
||||
}
|
||||
if (lang === 'json') {
|
||||
const { json } = await import('@codemirror/lang-json');
|
||||
return json();
|
||||
}
|
||||
if (lang === 'yaml') {
|
||||
const { yaml } = await import('@codemirror/lang-yaml');
|
||||
return yaml();
|
||||
}
|
||||
if (lang === 'xml') {
|
||||
const { xml } = await import('@codemirror/lang-xml');
|
||||
return xml();
|
||||
}
|
||||
if (lang === 'shell' || lang === 'bash') {
|
||||
const { StreamLanguage } = await import('@codemirror/language');
|
||||
const { shell } = await import('@codemirror/legacy-modes/mode/shell');
|
||||
return StreamLanguage.define(shell);
|
||||
}
|
||||
if (lang === 'markdown') {
|
||||
const { markdown, commonmarkLanguage } = await import('@codemirror/lang-markdown');
|
||||
const { GFM } = await import('@lezer/markdown');
|
||||
return markdown({
|
||||
base: commonmarkLanguage,
|
||||
extensions: GFM
|
||||
});
|
||||
}
|
||||
if (lang === 'typescript' || lang === 'ts' || lang === 'tsx') {
|
||||
const { javascript } = await import('@codemirror/lang-javascript');
|
||||
return javascript({ typescript: true, jsx: true });
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
// Initialize font size from store
|
||||
currentFontSize.value = appearanceStore.currentMobileEditorFontSize;
|
||||
|
||||
if (editorRef.value) {
|
||||
const langExt = await getLanguageExtension(props.language);
|
||||
console.log('[CodeMirrorMobileEditor DEBUG] onMounted - Initial language:', props.language, 'Fetched langExt:', langExt);
|
||||
const startState = createEditorState(props.modelValue, langExt);
|
||||
|
||||
view.value = new EditorView({
|
||||
state: startState,
|
||||
parent: editorRef.value,
|
||||
});
|
||||
editorRef.value.addEventListener('touchstart', onTouchStart, { passive: false });
|
||||
editorRef.value.addEventListener('touchmove', onTouchMove, { passive: false });
|
||||
editorRef.value.addEventListener('touchend', onTouchEnd, { passive: false });
|
||||
}
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (view.value) {
|
||||
view.value.destroy();
|
||||
view.value = null;
|
||||
}
|
||||
if (editorRef.value) {
|
||||
editorRef.value.removeEventListener('touchstart', onTouchStart);
|
||||
editorRef.value.removeEventListener('touchmove', onTouchMove);
|
||||
editorRef.value.removeEventListener('touchend', onTouchEnd);
|
||||
}
|
||||
if (debounceTimeout.value !== null) {
|
||||
clearTimeout(debounceTimeout.value);
|
||||
}
|
||||
});
|
||||
|
||||
watch(() => props.modelValue, (newValue) => {
|
||||
if (view.value && newValue !== view.value.state.doc.toString()) {
|
||||
view.value.dispatch({
|
||||
changes: { from: 0, to: view.value.state.doc.length, insert: newValue },
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
watch(() => props.language, async (newLanguage, oldLanguage) => {
|
||||
if (view.value && newLanguage !== oldLanguage) {
|
||||
const langExt = await getLanguageExtension(newLanguage);
|
||||
view.value.dispatch({
|
||||
effects: languageCompartment.reconfigure(langExt)
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
watch(() => appearanceStore.currentMobileEditorFontSize, (newSize) => {
|
||||
if (newSize !== currentFontSize.value) {
|
||||
currentFontSize.value = newSize;
|
||||
}
|
||||
});
|
||||
|
||||
const openSearch = () => {
|
||||
if (view.value) {
|
||||
openSearchPanel(view.value);
|
||||
}
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
focus: () => view.value?.focus(),
|
||||
openSearch, // + Expose openSearch method
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.codemirror-mobile-editor-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 200px;
|
||||
text-align: left;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.codemirror-mobile-editor-container :deep(.cm-gutters) {
|
||||
background-color: #1E1E1E !important;
|
||||
color: #858585 !important;
|
||||
border-right: 1px solid var(--border-color, #cccccc) !important;
|
||||
}
|
||||
|
||||
.codemirror-mobile-editor-container :deep(.cm-selectionBackground) {
|
||||
background-color: #5264ac !important;
|
||||
}
|
||||
</style>
|
||||
@@ -3,6 +3,7 @@ import { computed, ref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import MonacoEditor from './MonacoEditor.vue';
|
||||
import CodeMirrorMobileEditor from './CodeMirrorMobileEditor.vue'; // +++ Import new mobile editor
|
||||
import FileEditorTabs from './FileEditorTabs.vue';
|
||||
import { useFileEditorStore, type FileTab } from '../stores/fileEditor.store';
|
||||
import { useSettingsStore } from '../stores/settings.store';
|
||||
@@ -93,6 +94,7 @@ const startHeightPx = ref(0);
|
||||
const minWidth = 400; // 最小宽度
|
||||
const minHeight = 300; // 最小高度
|
||||
const encodingSelectRef = ref<HTMLSelectElement | null>(null); // +++ Ref for the select element +++
|
||||
const codeMirrorMobileEditorRef = ref<InstanceType<typeof CodeMirrorMobileEditor> | null>(null); // +++ Ref for CodeMirrorMobileEditor +++
|
||||
|
||||
// --- 计算属性,用于模板绑定 ---
|
||||
const popupStyle = computed(() => {
|
||||
@@ -337,7 +339,7 @@ const handleCloseTab = (tabId: string) => {
|
||||
const handleCloseOtherTabs = (targetTabId: string) => {
|
||||
console.log(`[FileEditorOverlay] handleCloseOtherTabs called for target: ${targetTabId}`); // Add log
|
||||
if (shareFileEditorTabsBoolean.value) {
|
||||
closeOtherTabs(targetTabId); // 修正:调用正确的 action 名称
|
||||
closeOtherTabs(targetTabId);
|
||||
} else {
|
||||
const sessionId = popupFileInfo.value?.sessionId;
|
||||
if (sessionId) {
|
||||
@@ -351,7 +353,7 @@ const handleCloseOtherTabs = (targetTabId: string) => {
|
||||
const handleCloseRightTabs = (targetTabId: string) => {
|
||||
console.log(`[FileEditorOverlay] handleCloseRightTabs called for target: ${targetTabId}`); // Add log
|
||||
if (shareFileEditorTabsBoolean.value) {
|
||||
closeTabsToTheRight(targetTabId); // 修正:调用正确的 action 名称
|
||||
closeTabsToTheRight(targetTabId);
|
||||
} else {
|
||||
const sessionId = popupFileInfo.value?.sessionId;
|
||||
if (sessionId) {
|
||||
@@ -421,20 +423,19 @@ const handleEditorScroll = ({ scrollTop, scrollLeft }: { scrollTop: number; scro
|
||||
const handleEditorFontSizeUpdate = (newSize: number) => {
|
||||
appearanceStore.setEditorFontSize(newSize);
|
||||
};
|
||||
|
||||
// +++ 打开搜索面板 +++
|
||||
const handleOpenSearch = () => {
|
||||
if (codeMirrorMobileEditorRef.value) {
|
||||
codeMirrorMobileEditorRef.value.openSearch();
|
||||
}
|
||||
};
|
||||
|
||||
// 关闭弹窗 (保持不变)
|
||||
const handleCloseContainer = () => {
|
||||
// 关闭前不再检查本地修改状态,因为没有本地状态了
|
||||
// 如果需要检查 store 中 activeTab 的修改状态,可以在这里添加逻辑
|
||||
// if (activeTab.value?.isModified) { ... }
|
||||
isVisible.value = false;
|
||||
// 不需要重置本地状态了
|
||||
};
|
||||
|
||||
// 最小化编辑器容器 (如果需要实现)
|
||||
// const handleMinimizeContainer = () => {
|
||||
// setEditorVisibility('minimized');
|
||||
// };
|
||||
|
||||
// --- 拖拽调整大小逻辑 ---
|
||||
const startResize = (event: MouseEvent) => {
|
||||
@@ -478,20 +479,8 @@ watch(popupTrigger, () => {
|
||||
const { filePath, sessionId } = popupFileInfo.value;
|
||||
console.log(`[FileEditorOverlay] Triggered for file: ${filePath} in session: ${sessionId}`);
|
||||
|
||||
// 仅显示弹窗,激活逻辑由各自 store 的 openFile/openFileInSession 处理
|
||||
// 或者由 handleActivateTab 处理用户点击
|
||||
isVisible.value = true;
|
||||
|
||||
// --- 确保激活状态正确 (重要) ---
|
||||
// 在非共享模式下,FileManager 调用 openFileInSession 时会设置会话内的 activeTabId。
|
||||
// 在共享模式下,FileManager 调用 openFile 时会设置全局的 activeTabId。
|
||||
// 这里不再需要强制调用 setActiveTab,因为触发弹窗时,对应的 store 应该已经处理了激活。
|
||||
// 如果发现激活不正确,问题可能在 FileManager 或对应的 store action 中。
|
||||
|
||||
// 检查激活状态 (调试用)
|
||||
// nextTick(() => { // 确保在 DOM 更新后检查
|
||||
// console.log(`[FileEditorOverlay] Popup shown. Current activeTabId: ${activeTabId.value}, Active Tab Object:`, activeTab.value);
|
||||
// });
|
||||
|
||||
});
|
||||
|
||||
@@ -500,7 +489,6 @@ watch(activeTab, () => {
|
||||
updateSelectWidth();
|
||||
}, { immediate: true }); // immediate: true ensures it runs on initial load too
|
||||
|
||||
// +++ Watch for changes in the selected encoding to update width +++
|
||||
watch(currentSelectedEncoding, () => {
|
||||
updateSelectWidth();
|
||||
});
|
||||
@@ -557,6 +545,15 @@ onBeforeUnmount(() => {
|
||||
<span v-if="currentTabSaveStatus === 'saving'" class="save-status saving">{{ t('fileManager.saving') }}...</span>
|
||||
<span v-if="currentTabSaveStatus === 'success'" class="save-status success">✅ {{ t('fileManager.saveSuccess') }}</span>
|
||||
<span v-if="currentTabSaveStatus === 'error'" class="save-status error">❌ {{ t('fileManager.saveError') }}: {{ currentTabSaveError }}</span>
|
||||
<!-- +++ 移动端搜索按钮 (Font Awesome) +++ -->
|
||||
<button
|
||||
v-if="props.isMobile && activeTab && !currentTabIsLoading"
|
||||
@click="handleOpenSearch"
|
||||
class="search-btn"
|
||||
:title="t('fileManager.actions.search', 'Search')"
|
||||
>
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
<button @click="handleSaveRequest" :disabled="currentTabIsSaving || currentTabIsLoading || !!currentTabLoadingError || !activeTab" class="save-btn">
|
||||
{{ t('fileManager.actions.save') }}
|
||||
</button>
|
||||
@@ -575,9 +572,11 @@ onBeforeUnmount(() => {
|
||||
<div class="editor-content-area">
|
||||
<div v-if="currentTabIsLoading" class="editor-loading">{{ t('fileManager.loadingFile') }}</div>
|
||||
<div v-else-if="currentTabLoadingError" class="editor-error">{{ currentTabLoadingError }}</div>
|
||||
|
||||
<!-- Desktop Editor -->
|
||||
<MonacoEditor
|
||||
v-else-if="activeTab"
|
||||
:key="activeTab.id"
|
||||
v-else-if="activeTab && !props.isMobile"
|
||||
:key="`monaco-${activeTab.id}`"
|
||||
v-model="activeEditorContent"
|
||||
:language="currentTabLanguage"
|
||||
:font-family="currentEditorFontFamily"
|
||||
@@ -586,9 +585,19 @@ onBeforeUnmount(() => {
|
||||
:font-size="currentEditorFontSize"
|
||||
@request-save="handleSaveRequest"
|
||||
@update:fontSize="handleEditorFontSizeUpdate"
|
||||
:initialScrollTop="activeTab?.scrollTop ?? 0"
|
||||
:initialScrollLeft="activeTab?.scrollLeft ?? 0"
|
||||
@update:scrollPosition="handleEditorScroll"
|
||||
:initialScrollTop="activeTab?.scrollTop ?? 0"
|
||||
:initialScrollLeft="activeTab?.scrollLeft ?? 0"
|
||||
@update:scrollPosition="handleEditorScroll"
|
||||
/>
|
||||
<!-- Mobile Editor -->
|
||||
<CodeMirrorMobileEditor
|
||||
v-else-if="activeTab && props.isMobile"
|
||||
:key="`cm-${activeTab.id}`"
|
||||
v-model="activeEditorContent"
|
||||
:language="currentTabLanguage"
|
||||
class="editor-instance"
|
||||
@request-save="handleSaveRequest"
|
||||
ref="codeMirrorMobileEditorRef"
|
||||
/>
|
||||
<!-- 如果容器可见但没有活动标签页 -->
|
||||
<div v-else class="editor-placeholder">{{ t('fileManager.selectFileToEdit') }}</div>
|
||||
@@ -805,6 +814,29 @@ onBeforeUnmount(() => {
|
||||
background-color: #45a049;
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.75rem;
|
||||
height: 1.75rem;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
border-radius: 0.25rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s, color 0.2s;
|
||||
padding: 0;
|
||||
color: #ccc;
|
||||
}
|
||||
.search-btn:hover {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
color: #f0f0f0;
|
||||
}
|
||||
.search-btn i {
|
||||
font-size: 1rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.save-status {
|
||||
font-size: 0.9em;
|
||||
padding: 0.2rem 0.5rem;
|
||||
@@ -838,33 +870,7 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
|
||||
/* 最小化状态样式 (可选) */
|
||||
/*
|
||||
.editor-minimized-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background-color: #333;
|
||||
color: #f0f0f0;
|
||||
padding: 0.5rem 1rem;
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
cursor: pointer;
|
||||
z-index: 1001;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
.editor-minimized-bar button {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #ccc;
|
||||
cursor: pointer;
|
||||
}
|
||||
*/
|
||||
|
||||
/* +++ 编码选择器样式 (copied from FileEditorContainer) +++ */
|
||||
.encoding-select-wrapper {
|
||||
display: inline-block; /* 让 wrapper 包裹内容 */
|
||||
vertical-align: middle; /* 垂直居中对齐 */
|
||||
@@ -879,7 +885,6 @@ onBeforeUnmount(() => {
|
||||
font-size: 0.85em;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
/* width: auto; */ /* JS will control width via style property */
|
||||
}
|
||||
|
||||
.encoding-select:hover {
|
||||
|
||||
@@ -29,7 +29,7 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: 'Consolas, "Courier New", monospace',
|
||||
},
|
||||
fontSize: { // 新增 prop
|
||||
fontSize: {
|
||||
type: Number,
|
||||
default: 14, // 默认字体大小
|
||||
},
|
||||
|
||||
@@ -129,6 +129,12 @@ export const useAppearanceStore = defineStore('appearance', () => {
|
||||
const currentEditorFontFamily = computed<string>(() => {
|
||||
return appearanceSettings.value.editorFontFamily || 'Consolas, "Noto Sans SC", "Microsoft YaHei"'; // 提供默认值
|
||||
});
|
||||
|
||||
// 当前移动端编辑器字体大小
|
||||
const currentMobileEditorFontSize = computed<number>(() => {
|
||||
const size = appearanceSettings.value.mobileEditorFontSize;
|
||||
return typeof size === 'number' && size > 0 ? size : 16; // 默认 16
|
||||
});
|
||||
|
||||
// 终端背景是否启用
|
||||
const isTerminalBackgroundEnabled = computed<boolean>(() => {
|
||||
@@ -342,6 +348,14 @@ export const useAppearanceStore = defineStore('appearance', () => {
|
||||
async function setEditorFontFamily(fontFamily: string) {
|
||||
await updateAppearanceSettings({ editorFontFamily: fontFamily });
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置移动端编辑器字体大小
|
||||
* @param size 字体大小 (数字)
|
||||
*/
|
||||
async function setMobileEditorFontSize(size: number) {
|
||||
await updateAppearanceSettings({ mobileEditorFontSize: size });
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置终端背景是否启用
|
||||
@@ -890,7 +904,8 @@ export const useAppearanceStore = defineStore('appearance', () => {
|
||||
terminalFontSizeDesktop, // + 用于在设置中分别显示/设置桌面端字号
|
||||
terminalFontSizeMobile, // + 用于在设置中分别显示/设置移动端字号
|
||||
currentEditorFontSize,
|
||||
currentEditorFontFamily, // 新增
|
||||
currentMobileEditorFontSize, // 移动端编辑器字号 getter
|
||||
currentEditorFontFamily,
|
||||
pageBackgroundImage,
|
||||
terminalBackgroundImage,
|
||||
currentTerminalBackgroundOverlayOpacity,
|
||||
@@ -904,7 +919,8 @@ export const useAppearanceStore = defineStore('appearance', () => {
|
||||
setTerminalFontSize, // 设置桌面端字体大小
|
||||
setTerminalFontSizeMobile, // + 设置移动端字体大小
|
||||
setEditorFontSize,
|
||||
setEditorFontFamily, // 新增
|
||||
setMobileEditorFontSize, // 设置移动端编辑器字号 action
|
||||
setEditorFontFamily,
|
||||
setTerminalBackgroundEnabled,
|
||||
createTerminalTheme,
|
||||
updateTerminalTheme,
|
||||
|
||||
@@ -11,7 +11,8 @@ export interface AppearanceSettings {
|
||||
terminalFontSizeMobile?: number; // 移动端字体大小
|
||||
terminalBackgroundImage?: string;
|
||||
pageBackgroundImage?: string;
|
||||
editorFontSize?: number;
|
||||
editorFontSize?: number; // 桌面端编辑器字号
|
||||
mobileEditorFontSize?: number; // 移动端编辑器字号
|
||||
editorFontFamily?: string | null; // Monaco Editor 字体偏好
|
||||
terminalBackgroundEnabled?: boolean; // 终端背景是否启用
|
||||
terminalBackgroundOverlayOpacity?: number; // 终端背景蒙版透明度 (0-1)
|
||||
|
||||
Reference in New Issue
Block a user