feat(box): 升级版本号并优化代码执行功能

-将版本号从 0.0.2 修改为 0.1.2
- 移除了异常时抛出的 RuntimeException
- 新增了 C 语言和 Java代码的执行功能
- 优化了 Python 代码的执行方式- 添加了代码编辑器的前端界面
- 新增了 QQ音乐文件解密工具的 UI 界面
- 添加了 C++ 解密库的框架
This commit is contained in:
tzdwindows 7
2025-05-24 09:36:48 +08:00
parent f632b9584d
commit e475e84851
53 changed files with 42629 additions and 9 deletions

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="JavaScriptLibraryMappings"> <component name="JavaScriptLibraryMappings">
<file url="file://$PROJECT_DIR$" libraries="{codemirror, font-awesome, monaco-editor}" />
<file url="file://$PROJECT_DIR$/src/main" libraries="{highlight.js, katex, marked, mathjax}" /> <file url="file://$PROJECT_DIR$/src/main" libraries="{highlight.js, katex, marked, mathjax}" />
</component> </component>
</project> </project>

View File

@@ -69,6 +69,9 @@ dependencies {
implementation 'com.formdev:flatlaf-intellij-themes:3.2.1' // 官方主题包 implementation 'com.formdev:flatlaf-intellij-themes:3.2.1' // 官方主题包
implementation 'org.python:jython-standalone:2.7.3' implementation 'org.python:jython-standalone:2.7.3'
implementation 'org.graalvm.python:python-embedding:24.2.1'
implementation files('libs/JNC-1.0-jnc.jar')
implementation 'org.fxmisc.richtext:richtextfx:0.11.0' // 更新后的richtextfx implementation 'org.fxmisc.richtext:richtextfx:0.11.0' // 更新后的richtextfx
implementation 'org.bitbucket.mstrobel:procyon-core:0.5.36' // 使用JitPack版本 implementation 'org.bitbucket.mstrobel:procyon-core:0.5.36' // 使用JitPack版本
@@ -146,6 +149,8 @@ dependencies {
implementation 'com.github.axet:TarsosDSP:2.4' implementation 'com.github.axet:TarsosDSP:2.4'
implementation 'org.json:json:20231013'
// Eclipse 组件 // Eclipse 组件
// https://mvnrepository.com/artifact/org.eclipse.swt/org.eclipse.swt.win32.win32.x86_64 // https://mvnrepository.com/artifact/org.eclipse.swt/org.eclipse.swt.win32.win32.x86_64
//implementation 'org.eclipse.swt:org.eclipse.swt.win32.win32.x86_64:4.3' //implementation 'org.eclipse.swt:org.eclipse.swt.win32.win32.x86_64:4.3'
@@ -155,6 +160,9 @@ dependencies {
//implementation 'org.eclipse.platform:org.eclipse.jface.text:3.27.0' // 使用兼容版本 //implementation 'org.eclipse.platform:org.eclipse.jface.text:3.27.0' // 使用兼容版本
//implementation 'org.eclipse.platform:org.eclipse.core.runtime:3.33.0' //implementation 'org.eclipse.platform:org.eclipse.core.runtime:3.33.0'
//implementation 'org.eclipse.platform:org.eclipse.equinox.common:3.20.0' //implementation 'org.eclipse.platform:org.eclipse.equinox.common:3.20.0'
} }
// 分离依赖项到 libs 目录 // 分离依赖项到 libs 目录

364
javascript/CCodeEditor.html Normal file
View File

@@ -0,0 +1,364 @@
<!DOCTYPE html>
<html>
<head>
<title>C语言编辑器</title>
<style>
body {
margin: 0;
height: 100vh;
background: #2B2B2B;
font-family: 'JetBrains Mono', 'Consolas', monospace;
}
#editor {
width: 100vw;
height: 100vh;
}
.mtk5.keyword { color: #CC7832; font-weight: bold; }
.mtk5.function { color: #FFC66D; }
.mtk5.variable { color: #9876AA; }
.mtk5.comment { color: #808080; }
.mtk5.string { color: #6A8759; }
.mtk5.number { color: #6897BB; }
.doxygen-tag { color: #CC7832; }
.doxygen-param { color: #9876AA; }
.monaco-editor.vs-dark .monaco-editor-background { background: #2B2B2B !important; }
.monaco-editor .margin { background: #313335 !important; }
#container {
display: flex;
flex-direction: column;
height: 100vh;
}
#toolbar {
background: #1E1E1E;
padding: 8px;
border-bottom: 1px solid #333;
}
#executeBtn {
background: #3276B1;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
font-family: 'JetBrains Mono';
}
#console {
height: 200px;
background: #1E1E1E;
border-top: 1px solid #333;
padding: 10px;
overflow-y: auto;
}
#output {
color: #B5B5B5;
margin: 0;
font-family: 'JetBrains Mono';
font-size: 14px;
white-space: pre-wrap;
}
</style>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap" rel="stylesheet">
</head>
<body>
<div id="container">
<div id="toolbar">
<button id="executeBtn">▶ 执行</button>
</div>
<div id="editor"></div>
<div id="console">
<pre id="output"></pre>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.49.0/min/vs/loader.min.js"></script>
<script>
require.config({
paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.49.0/min/vs' },
'vs/nls': {
availableLanguages: { '*': 'zh-cn' }
}
});
require(['vs/editor/editor.main'], function() {
// 输出内容到控制台
function appendOutput(text, isError = false) {
const output = document.getElementById('output');
const div = document.createElement('div');
div.style.color = isError ? '#FF6666' : '#B5B5B5';
div.textContent = text;
output.appendChild(div);
output.scrollTop = output.scrollHeight;
}
// 清空控制台
function clearOutput() {
document.getElementById('output').innerHTML = '';
}
document.getElementById('executeBtn').addEventListener('click', () => {
const code = editor.getValue();
// 发送执行请求到Java后端
window.cefQuery({
request: JSON.stringify({
type: "executeCode",
code: code,
language: "c"
}),
onSuccess: (response) => {
const result = JSON.parse(response);
appendOutput(result.output);
},
onFailure: (errorCode, errorMsg) => {
appendOutput(`执行错误 (${errorCode}): ${errorMsg}`, true);
}
});
});
monaco.languages.register({ id: 'c' });
// C语言关键字配置
const cKeywords = [
'auto', 'break', 'case', 'char', 'const', 'continue',
'default', 'do', 'double', 'else', 'enum', 'extern',
'float', 'for', 'goto', 'if', 'inline', 'int', 'long',
'register', 'return', 'short', 'signed', 'sizeof', 'static',
'struct', 'switch', 'typedef', 'union', 'unsigned', 'void',
'volatile', 'while', '_Alignas', '_Alignof', '_Atomic',
'_Bool', '_Complex', '_Generic', '_Imaginary', '_Noreturn',
'_Static_assert', '_Thread_local',"#include","#define"
];
// 语法高亮配置
monaco.languages.setMonarchTokensProvider('c', {
keywords: cKeywords,
tokenizer: {
root: [
[/for\s*\(/, {
cases: {
'@keywords': 'keyword',
'@default': 'keyword'
}
}],
[/if\s*\(/, 'keyword'],
[/\/\*\*/, 'comment.doxygen', '@doxygen'],
[/\/\*/, 'comment', '@comment'],
[/[a-zA-Z_]\w*(?=\s*\()/, 'function'],
[/[a-zA-Z_]\w*/, {
cases: {
'@keywords': 'keyword',
'@default': 'variable'
}
}],
{ include: '@whitespace' },
[/[{}()\[\]]/, '@brackets'],
[/[0-9]+/, 'number'],
[/"/, 'string', '@string'],
[/\/\/.*$/, 'comment'],
],
doxygen: [
[/\*\//, 'comment.doxygen', '@pop'],
[/@\w+/, 'doxygen-tag'],
[/\\[\w]+/, 'doxygen-param'],
[/[\s\S]/, 'comment.doxygen']
],
comment: [
[/\*\//, 'comment', '@pop'],
[/[\s\S]/, 'comment']
],
string: [
[/[^\\"]+/, 'string'],
[/\\["\\nrt]/, 'string.escape'],
[/"/, 'string', '@pop']
],
whitespace: [
[/[ \t\r\n]+/, 'white'],
],
}
});
// 定义跳转功能
monaco.languages.registerDefinitionProvider('c', {
provideDefinition: (model, position) => {
const word = model.getWordAtPosition(position);
if (!word) return [];
const funcMatches = model.findMatches(
`\\b(\\w+)\\s+${word.word}\\s*\\([^)]*\\)\\s*[;{]`,
true, true, false, null, true
);
const varMatches = model.findMatches(
`\\b(int|float|double|char|void|short|long|unsigned)\\s+${word.word}\\b`,
true, true, false, null, true
);
return [...funcMatches, ...varMatches].map(match => ({
uri: model.uri,
range: match.range
}));
}
});
// 自动补全配置
const systemFunctions = [
{
label: 'printf',
kind: monaco.languages.CompletionItemKind.Function,
insertText: 'printf("${1:format}", ${2:args});',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: {
value: '**格式化输出函数**\n\n参数:\n- `format`: 格式字符串 (例: "%d")\n- `...`: 可变参数列表'
}
},
{
label: 'main',
kind: monaco.languages.CompletionItemKind.Function,
insertText: 'int main(int ${1:argc}, char* ${2:argv[]}){\n ${3://is code}\n}',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: {
value: '**主函数**'
}
},
{
label: 'scanf',
kind: monaco.languages.CompletionItemKind.Function,
insertText: 'scanf("${1:format}", ${2:&var});',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: {
value: '**格式化输入函数**\n\n参数:\n- `format`: 格式字符串\n- `...`: 变量地址列表'
}
}
];
const codeSnippets = [
{
label: 'if',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: 'if (${1:condition}) {\n\t${2:// code}\n}',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: 'if条件语句'
},
{
label: 'for',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: 'for (int ${1:i} = 0; ${1:i} < ${2:count}; ${1:i}++) {\n\t${3:// code}\n}',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: 'for循环语句'
},
{
label: 'while',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: 'while (${1:condition}) {\n\t${2:// code}\n}',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: 'while循环语句'
},
{
label: 'switch',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: 'switch (${1:expression}) {\n\tcase ${2:value}:\n\t\t${3:// code}\n\t\tbreak;\n\tdefault:\n\t\t${4:// code}\n}',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: 'switch语句'
}
];
monaco.languages.registerCompletionItemProvider('c', {
triggerCharacters: ['.', ':', '$', '/', '@', '*'],
provideCompletionItems: (model, position) => {
const word = model.getWordUntilPosition(position);
const range = new monaco.Range(
position.lineNumber,
word.startColumn,
position.lineNumber,
word.endColumn
);
return {
suggestions: [
...cKeywords.map(keyword => ({
label: keyword,
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: keyword,
range: range
})),
...codeSnippets.map(snippet => ({
...snippet,
range: range
})),
...systemFunctions.map(func => ({
...func,
range: range
})),
...getCurrentVariables(model).map(v => ({
label: v.name,
kind: monaco.languages.CompletionItemKind.Variable,
detail: `类型: ${v.type}`,
insertText: v.name,
range: range
})),
...getCurrentFunctions(model).map(f => ({
label: f,
kind: monaco.languages.CompletionItemKind.Function,
detail: '用户定义函数',
insertText: f,
range: range
}))
]
};
}
});
// 创建编辑器实例
const editor = monaco.editor.create(document.getElementById('editor'), {
value: `#include <stdio.h>\n\nint main() {\n printf("Hello World\\n");\n return 0;\n}`,
language: 'c',
theme: 'vs-dark',
minimap: { enabled: true },
fontSize: 16,
lineNumbers: 'on',
roundedSelection: false,
scrollBeyondLastLine: false,
automaticLayout: true,
tabSize: 4,
suggest: {
showKeywords: true,
showSnippets: true
},
glyphMargin: true,
lightbulb: { enabled: true }
});
// 辅助函数
function getCurrentVariables(model) {
const varRegex = /\b(int|float|double|char|void|short|long|unsigned)\s+([a-zA-Z_][\w,\s*]*)/g;
const variables = [];
let match;
while ((match = varRegex.exec(model.getValue()))) {
const type = match[1];
const names = match[2].split(',').map(s => s.trim());
names.forEach(name => {
variables.push({
name: name.replace(/\*+/g, '').trim(),
type: type
});
});
}
return variables;
}
function getCurrentFunctions(model) {
const funcRegex = /(\w+)\s*\([^)]*\)\s*\{/g;
return Array.from(model.getValue().matchAll(funcRegex))
.map(m => m[1])
.filter(f => !['if','while','for','switch'].includes(f));
}
window.addEventListener('resize', () => editor.layout());
});
</script>
</body>
</html>

164
javascript/CodeEditor.html Normal file
View File

@@ -0,0 +1,164 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>在线代码编辑器</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.36.1/min/vs/loader.min.js"></script>
<style>
:root {
--bg-dark: #2b2b2b;
--bg-light: #383838;
--text: #cccccc;
--blue: #569cd6;
--green: #6a9955;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: var(--bg-dark);
color: var(--text);
font-family: 'Microsoft YaHei', sans-serif;
height: 100vh;
display: flex;
flex-direction: column;
}
#toolbar {
background: var(--bg-light);
padding: 10px;
display: flex;
gap: 20px;
align-items: center;
}
.btn {
background: var(--blue);
color: white;
border: none;
padding: 8px 15px;
border-radius: 3px;
cursor: pointer;
transition: opacity 0.3s;
}
.btn:hover {
opacity: 0.8;
}
#language-select {
background: var(--bg-dark);
color: var(--text);
padding: 5px;
border: 1px solid #555;
}
#editor-container {
flex: 1;
position: relative;
}
#output {
background: #1e1e1e;
padding: 15px;
border-top: 2px solid #333;
height: 200px;
overflow-y: auto;
white-space: pre-wrap;
}
.status-bar {
background: var(--bg-light);
padding: 5px 10px;
font-size: 0.9em;
border-top: 1px solid #444;
}
</style>
</head>
<body>
<div id="toolbar">
<button class="btn" onclick="runCode()">▶ 运行 (Ctrl+Enter)</button>
<select id="language-select" onchange="changeLanguage()">
<option value="python">Python</option>
<option value="java">Java</option>
<option value="cpp">C++</option>
</select>
</div>
<div id="editor-container"></div>
<div class="status-bar">
<span id="status">就绪</span>
</div>
<div id="output"></div>
<script>
let editor;
require.config({ paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.36.1/min/vs' }});
require(['vs/editor/editor.main'], function() {
editor = monaco.editor.create(document.getElementById('editor-container'), {
value: getDefaultCode('python'),
language: 'python',
theme: 'vs-dark',
minimap: { enabled: true },
automaticLayout: true,
fontSize: 14,
scrollBeyondLastLine: false
});
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, runCode);
});
function getDefaultCode(lang) {
const templates = {
python: '# Python 示例\nprint("你好,世界!")\n',
java: '// Java 示例\npublic class Main {\n public static void main(String[] args) {\n System.out.println("你好,世界!");\n }\n}\n',
cpp: '// C++ 示例\n#include <iostream>\nusing namespace std;\n\nint main() {\n cout << "你好,世界!" << endl;\n return 0;\n}\n'
};
return templates[lang];
}
function changeLanguage() {
const lang = document.getElementById('language-select').value;
monaco.editor.setModelLanguage(editor.getModel(), lang);
editor.setValue(getDefaultCode(lang));
}
function runCode() {
const code = editor.getValue();
const language = document.getElementById('language-select').value;
const output = document.getElementById('output');
output.innerHTML = '正在执行...';
document.getElementById('status').textContent = '正在执行...';
const request = {
type: "executeCode",
code: code,
language: language
};
window.cefQuery({
request: JSON.stringify(request),
onSuccess: function(response) {
const result = JSON.parse(response);
output.innerHTML = result.output;
document.getElementById('status').textContent = '执行完成';
},
onFailure: function(errorCode, errorMsg) {
const error = JSON.parse(errorMsg);
output.innerHTML = `错误:${error.message}`;
document.getElementById('status').textContent = '执行失败';
}
});
}
</script>
</body>
</html>

View File

@@ -0,0 +1,349 @@
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("katex"));
else if(typeof define === 'function' && define.amd)
define(["katex"], factory);
else if(typeof exports === 'object')
exports["renderMathInElement"] = factory(require("katex"));
else
root["renderMathInElement"] = factory(root["katex"]);
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__771__) {
return /******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ 771:
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__771__;
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ !function() {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function() { return module['default']; } :
/******/ function() { return module; };
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ !function() {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = function(exports, definition) {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ !function() {
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ }();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
!function() {
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
"default": function() { return /* binding */ auto_render; }
});
// EXTERNAL MODULE: external "katex"
var external_katex_ = __webpack_require__(771);
var external_katex_default = /*#__PURE__*/__webpack_require__.n(external_katex_);
;// CONCATENATED MODULE: ./contrib/auto-render/splitAtDelimiters.js
/* eslint no-constant-condition:0 */
var findEndOfMath = function findEndOfMath(delimiter, text, startIndex) {
// Adapted from
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
var index = startIndex;
var braceLevel = 0;
var delimLength = delimiter.length;
while (index < text.length) {
var character = text[index];
if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) {
return index;
} else if (character === "\\") {
index++;
} else if (character === "{") {
braceLevel++;
} else if (character === "}") {
braceLevel--;
}
index++;
}
return -1;
};
var escapeRegex = function escapeRegex(string) {
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
};
var amsRegex = /^\\begin{/;
var splitAtDelimiters = function splitAtDelimiters(text, delimiters) {
var index;
var data = [];
var regexLeft = new RegExp("(" + delimiters.map(function (x) {
return escapeRegex(x.left);
}).join("|") + ")");
while (true) {
index = text.search(regexLeft);
if (index === -1) {
break;
}
if (index > 0) {
data.push({
type: "text",
data: text.slice(0, index)
});
text = text.slice(index); // now text starts with delimiter
} // ... so this always succeeds:
var i = delimiters.findIndex(function (delim) {
return text.startsWith(delim.left);
});
index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);
if (index === -1) {
break;
}
var rawData = text.slice(0, index + delimiters[i].right.length);
var math = amsRegex.test(rawData) ? rawData : text.slice(delimiters[i].left.length, index);
data.push({
type: "math",
data: math,
rawData: rawData,
display: delimiters[i].display
});
text = text.slice(index + delimiters[i].right.length);
}
if (text !== "") {
data.push({
type: "text",
data: text
});
}
return data;
};
/* harmony default export */ var auto_render_splitAtDelimiters = (splitAtDelimiters);
;// CONCATENATED MODULE: ./contrib/auto-render/auto-render.js
/* eslint no-console:0 */
/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
* API, we should copy it before mutating.
*/
var renderMathInText = function renderMathInText(text, optionsCopy) {
var data = auto_render_splitAtDelimiters(text, optionsCopy.delimiters);
if (data.length === 1 && data[0].type === 'text') {
// There is no formula in the text.
// Let's return null which means there is no need to replace
// the current text node with a new one.
return null;
}
var fragment = document.createDocumentFragment();
for (var i = 0; i < data.length; i++) {
if (data[i].type === "text") {
fragment.appendChild(document.createTextNode(data[i].data));
} else {
var span = document.createElement("span");
var math = data[i].data; // Override any display mode defined in the settings with that
// defined by the text itself
optionsCopy.displayMode = data[i].display;
try {
if (optionsCopy.preProcess) {
math = optionsCopy.preProcess(math);
}
external_katex_default().render(math, span, optionsCopy);
} catch (e) {
if (!(e instanceof (external_katex_default()).ParseError)) {
throw e;
}
optionsCopy.errorCallback("KaTeX auto-render: Failed to parse `" + data[i].data + "` with ", e);
fragment.appendChild(document.createTextNode(data[i].rawData));
continue;
}
fragment.appendChild(span);
}
}
return fragment;
};
var renderElem = function renderElem(elem, optionsCopy) {
for (var i = 0; i < elem.childNodes.length; i++) {
var childNode = elem.childNodes[i];
if (childNode.nodeType === 3) {
// Text node
// Concatenate all sibling text nodes.
// Webkit browsers split very large text nodes into smaller ones,
// so the delimiters may be split across different nodes.
var textContentConcat = childNode.textContent;
var sibling = childNode.nextSibling;
var nSiblings = 0;
while (sibling && sibling.nodeType === Node.TEXT_NODE) {
textContentConcat += sibling.textContent;
sibling = sibling.nextSibling;
nSiblings++;
}
var frag = renderMathInText(textContentConcat, optionsCopy);
if (frag) {
// Remove extra text nodes
for (var j = 0; j < nSiblings; j++) {
childNode.nextSibling.remove();
}
i += frag.childNodes.length - 1;
elem.replaceChild(frag, childNode);
} else {
// If the concatenated text does not contain math
// the siblings will not either
i += nSiblings;
}
} else if (childNode.nodeType === 1) {
(function () {
// Element node
var className = ' ' + childNode.className + ' ';
var shouldRender = optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && optionsCopy.ignoredClasses.every(function (x) {
return className.indexOf(' ' + x + ' ') === -1;
});
if (shouldRender) {
renderElem(childNode, optionsCopy);
}
})();
} // Otherwise, it's something else, and ignore it.
}
};
var renderMathInElement = function renderMathInElement(elem, options) {
if (!elem) {
throw new Error("No element provided to render");
}
var optionsCopy = {}; // Object.assign(optionsCopy, option)
for (var option in options) {
if (options.hasOwnProperty(option)) {
optionsCopy[option] = options[option];
}
} // default options
optionsCopy.delimiters = optionsCopy.delimiters || [{
left: "$$",
right: "$$",
display: true
}, {
left: "\\(",
right: "\\)",
display: false
}, // LaTeX uses $…$, but it ruins the display of normal `$` in text:
// {left: "$", right: "$", display: false},
// $ must come after $$
// Render AMS environments even if outside $$…$$ delimiters.
{
left: "\\begin{equation}",
right: "\\end{equation}",
display: true
}, {
left: "\\begin{align}",
right: "\\end{align}",
display: true
}, {
left: "\\begin{alignat}",
right: "\\end{alignat}",
display: true
}, {
left: "\\begin{gather}",
right: "\\end{gather}",
display: true
}, {
left: "\\begin{CD}",
right: "\\end{CD}",
display: true
}, {
left: "\\[",
right: "\\]",
display: true
}];
optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code", "option"];
optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; // Enable sharing of global macros defined via `\gdef` between different
// math elements within a single call to `renderMathInElement`.
optionsCopy.macros = optionsCopy.macros || {};
renderElem(elem, optionsCopy);
};
/* harmony default export */ var auto_render = (renderMathInElement);
}();
__webpack_exports__ = __webpack_exports__["default"];
/******/ return __webpack_exports__;
/******/ })()
;
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,185 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
/**
* Tag-closer extension for CodeMirror.
*
* This extension adds an "autoCloseTags" option that can be set to
* either true to get the default behavior, or an object to further
* configure its behavior.
*
* These are supported options:
*
* `whenClosing` (default true)
* Whether to autoclose when the '/' of a closing tag is typed.
* `whenOpening` (default true)
* Whether to autoclose the tag when the final '>' of an opening
* tag is typed.
* `dontCloseTags` (default is empty tags for HTML, none for XML)
* An array of tag names that should not be autoclosed.
* `indentTags` (default is block tags for HTML, none for XML)
* An array of tag names that should, when opened, cause a
* blank line to be added inside the tag, and the blank line and
* closing line to be indented.
* `emptyTags` (default is none)
* An array of XML tag names that should be autoclosed with '/>'.
*
* See demos/closetag.html for a usage example.
*/
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../fold/xml-fold"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) {
if (old != CodeMirror.Init && old)
cm.removeKeyMap("autoCloseTags");
if (!val) return;
var map = {name: "autoCloseTags"};
if (typeof val != "object" || val.whenClosing !== false)
map["'/'"] = function(cm) { return autoCloseSlash(cm); };
if (typeof val != "object" || val.whenOpening !== false)
map["'>'"] = function(cm) { return autoCloseGT(cm); };
cm.addKeyMap(map);
});
var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param",
"source", "track", "wbr"];
var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4",
"h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"];
function autoCloseGT(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), replacements = [];
var opt = cm.getOption("autoCloseTags");
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var pos = ranges[i].head, tok = cm.getTokenAt(pos);
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
var tagInfo = inner.mode.xmlCurrentTag && inner.mode.xmlCurrentTag(state)
var tagName = tagInfo && tagInfo.name
if (!tagName) return CodeMirror.Pass
var html = inner.mode.configuration == "html";
var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);
var lowerTagName = tagName.toLowerCase();
// Don't process the '>' at the end of an end-tag or self-closing tag
if (!tagName ||
tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) ||
tok.type == "tag" && tagInfo.close ||
tok.string.indexOf("/") == (pos.ch - tok.start - 1) || // match something like <someTagName />
dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||
closingTagExists(cm, inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state) || [], tagName, pos, true))
return CodeMirror.Pass;
var emptyTags = typeof opt == "object" && opt.emptyTags;
if (emptyTags && indexOf(emptyTags, tagName) > -1) {
replacements[i] = { text: "/>", newPos: CodeMirror.Pos(pos.line, pos.ch + 2) };
continue;
}
var indent = indentTags && indexOf(indentTags, lowerTagName) > -1;
replacements[i] = {indent: indent,
text: ">" + (indent ? "\n\n" : "") + "</" + tagName + ">",
newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)};
}
var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnAutoClose);
for (var i = ranges.length - 1; i >= 0; i--) {
var info = replacements[i];
cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert");
var sel = cm.listSelections().slice(0);
sel[i] = {head: info.newPos, anchor: info.newPos};
cm.setSelections(sel);
if (!dontIndentOnAutoClose && info.indent) {
cm.indentLine(info.newPos.line, null, true);
cm.indentLine(info.newPos.line + 1, null, true);
}
}
}
function autoCloseCurrent(cm, typingSlash) {
var ranges = cm.listSelections(), replacements = [];
var head = typingSlash ? "/" : "</";
var opt = cm.getOption("autoCloseTags");
var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnSlash);
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var pos = ranges[i].head, tok = cm.getTokenAt(pos);
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
if (typingSlash && (tok.type == "string" || tok.string.charAt(0) != "<" ||
tok.start != pos.ch - 1))
return CodeMirror.Pass;
// Kludge to get around the fact that we are not in XML mode
// when completing in JS/CSS snippet in htmlmixed mode. Does not
// work for other XML embedded languages (there is no general
// way to go from a mixed mode to its current XML state).
var replacement, mixed = inner.mode.name != "xml" && cm.getMode().name == "htmlmixed"
if (mixed && inner.mode.name == "javascript") {
replacement = head + "script";
} else if (mixed && inner.mode.name == "css") {
replacement = head + "style";
} else {
var context = inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state)
var top = context.length ? context[context.length - 1] : ""
if (!context || (context.length && closingTagExists(cm, context, top, pos)))
return CodeMirror.Pass;
replacement = head + top
}
if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">";
replacements[i] = replacement;
}
cm.replaceSelections(replacements);
ranges = cm.listSelections();
if (!dontIndentOnAutoClose) {
for (var i = 0; i < ranges.length; i++)
if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)
cm.indentLine(ranges[i].head.line);
}
}
function autoCloseSlash(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
return autoCloseCurrent(cm, true);
}
CodeMirror.commands.closeTag = function(cm) { return autoCloseCurrent(cm); };
function indexOf(collection, elt) {
if (collection.indexOf) return collection.indexOf(elt);
for (var i = 0, e = collection.length; i < e; ++i)
if (collection[i] == elt) return i;
return -1;
}
// If xml-fold is loaded, we use its functionality to try and verify
// whether a given tag is actually unclosed.
function closingTagExists(cm, context, tagName, pos, newTag) {
if (!CodeMirror.scanForClosingTag) return false;
var end = Math.min(cm.lastLine() + 1, pos.line + 500);
var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end);
if (!nextClose || nextClose.tag != tagName) return false;
// If the immediate wrapping context contains onCx instances of
// the same tag, a closing tag only exists if there are at least
// that many closing tags of that type following.
var onCx = newTag ? 1 : 0
for (var i = context.length - 1; i >= 0; i--) {
if (context[i] == tagName) ++onCx
else break
}
pos = nextClose.to;
for (var i = 1; i < onCx; i++) {
var next = CodeMirror.scanForClosingTag(cm, pos, null, end);
if (!next || next.tag != tagName) return false;
pos = next.to;
}
return true;
}
});

View File

@@ -0,0 +1,36 @@
.CodeMirror-hints {
position: absolute;
z-index: 10;
overflow: hidden;
list-style: none;
margin: 0;
padding: 2px;
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
box-shadow: 2px 3px 5px rgba(0,0,0,.2);
border-radius: 3px;
border: 1px solid silver;
background: white;
font-size: 90%;
font-family: monospace;
max-height: 20em;
overflow-y: auto;
}
.CodeMirror-hint {
margin: 0;
padding: 0 4px;
border-radius: 2px;
white-space: pre;
color: black;
cursor: pointer;
}
li.CodeMirror-hint-active {
background: #08f;
color: white;
}

View File

@@ -0,0 +1,529 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
// declare global: DOMRect
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var HINT_ELEMENT_CLASS = "CodeMirror-hint";
var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
// This is the old interface, kept around for now to stay
// backwards-compatible.
CodeMirror.showHint = function(cm, getHints, options) {
if (!getHints) return cm.showHint(options);
if (options && options.async) getHints.async = true;
var newOpts = {hint: getHints};
if (options) for (var prop in options) newOpts[prop] = options[prop];
return cm.showHint(newOpts);
};
CodeMirror.defineExtension("showHint", function(options) {
options = parseOptions(this, this.getCursor("start"), options);
var selections = this.listSelections()
if (selections.length > 1) return;
// By default, don't allow completion when something is selected.
// A hint function can have a `supportsSelection` property to
// indicate that it can handle selections.
if (this.somethingSelected()) {
if (!options.hint.supportsSelection) return;
// Don't try with cross-line selections
for (var i = 0; i < selections.length; i++)
if (selections[i].head.line != selections[i].anchor.line) return;
}
if (this.state.completionActive) this.state.completionActive.close();
var completion = this.state.completionActive = new Completion(this, options);
if (!completion.options.hint) return;
CodeMirror.signal(this, "startCompletion", this);
completion.update(true);
});
CodeMirror.defineExtension("closeHint", function() {
if (this.state.completionActive) this.state.completionActive.close()
})
function Completion(cm, options) {
this.cm = cm;
this.options = options;
this.widget = null;
this.debounce = 0;
this.tick = 0;
this.startPos = this.cm.getCursor("start");
this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
if (this.options.updateOnCursorActivity) {
var self = this;
cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
}
}
var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
return setTimeout(fn, 1000/60);
};
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
Completion.prototype = {
close: function() {
if (!this.active()) return;
this.cm.state.completionActive = null;
this.tick = null;
if (this.options.updateOnCursorActivity) {
this.cm.off("cursorActivity", this.activityFunc);
}
if (this.widget && this.data) CodeMirror.signal(this.data, "close");
if (this.widget) this.widget.close();
CodeMirror.signal(this.cm, "endCompletion", this.cm);
},
active: function() {
return this.cm.state.completionActive == this;
},
pick: function(data, i) {
var completion = data.list[i], self = this;
this.cm.operation(function() {
if (completion.hint)
completion.hint(self.cm, data, completion);
else
self.cm.replaceRange(getText(completion), completion.from || data.from,
completion.to || data.to, "complete");
CodeMirror.signal(data, "pick", completion);
self.cm.scrollIntoView();
});
if (this.options.closeOnPick) {
this.close();
}
},
cursorActivity: function() {
if (this.debounce) {
cancelAnimationFrame(this.debounce);
this.debounce = 0;
}
var identStart = this.startPos;
if(this.data) {
identStart = this.data.from;
}
var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
pos.ch < identStart.ch || this.cm.somethingSelected() ||
(!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
this.close();
} else {
var self = this;
this.debounce = requestAnimationFrame(function() {self.update();});
if (this.widget) this.widget.disable();
}
},
update: function(first) {
if (this.tick == null) return
var self = this, myTick = ++this.tick
fetchHints(this.options.hint, this.cm, this.options, function(data) {
if (self.tick == myTick) self.finishUpdate(data, first)
})
},
finishUpdate: function(data, first) {
if (this.data) CodeMirror.signal(this.data, "update");
var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
if (this.widget) this.widget.close();
this.data = data;
if (data && data.list.length) {
if (picked && data.list.length == 1) {
this.pick(data, 0);
} else {
this.widget = new Widget(this, data);
CodeMirror.signal(data, "shown");
}
}
}
};
function parseOptions(cm, pos, options) {
var editor = cm.options.hintOptions;
var out = {};
for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
if (editor) for (var prop in editor)
if (editor[prop] !== undefined) out[prop] = editor[prop];
if (options) for (var prop in options)
if (options[prop] !== undefined) out[prop] = options[prop];
if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
return out;
}
function getText(completion) {
if (typeof completion == "string") return completion;
else return completion.text;
}
function buildKeyMap(completion, handle) {
var baseMap = {
Up: function() {handle.moveFocus(-1);},
Down: function() {handle.moveFocus(1);},
PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
Home: function() {handle.setFocus(0);},
End: function() {handle.setFocus(handle.length - 1);},
Enter: handle.pick,
Tab: handle.pick,
Esc: handle.close
};
var mac = /Mac/.test(navigator.platform);
if (mac) {
baseMap["Ctrl-P"] = function() {handle.moveFocus(-1);};
baseMap["Ctrl-N"] = function() {handle.moveFocus(1);};
}
var custom = completion.options.customKeys;
var ourMap = custom ? {} : baseMap;
function addBinding(key, val) {
var bound;
if (typeof val != "string")
bound = function(cm) { return val(cm, handle); };
// This mechanism is deprecated
else if (baseMap.hasOwnProperty(val))
bound = baseMap[val];
else
bound = val;
ourMap[key] = bound;
}
if (custom)
for (var key in custom) if (custom.hasOwnProperty(key))
addBinding(key, custom[key]);
var extra = completion.options.extraKeys;
if (extra)
for (var key in extra) if (extra.hasOwnProperty(key))
addBinding(key, extra[key]);
return ourMap;
}
function getHintElement(hintsElement, el) {
while (el && el != hintsElement) {
if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
el = el.parentNode;
}
}
function Widget(completion, data) {
this.id = "cm-complete-" + Math.floor(Math.random(1e6))
this.completion = completion;
this.data = data;
this.picked = false;
var widget = this, cm = completion.cm;
var ownerDocument = cm.getInputField().ownerDocument;
var parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow;
var hints = this.hints = ownerDocument.createElement("ul");
hints.setAttribute("role", "listbox")
hints.setAttribute("aria-expanded", "true")
hints.id = this.id
var theme = completion.cm.options.theme;
hints.className = "CodeMirror-hints " + theme;
this.selectedHint = data.selectedHint || 0;
var completions = data.list;
for (var i = 0; i < completions.length; ++i) {
var elt = hints.appendChild(ownerDocument.createElement("li")), cur = completions[i];
var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
if (cur.className != null) className = cur.className + " " + className;
elt.className = className;
if (i == this.selectedHint) elt.setAttribute("aria-selected", "true")
elt.id = this.id + "-" + i
elt.setAttribute("role", "option")
if (cur.render) cur.render(elt, data, cur);
else elt.appendChild(ownerDocument.createTextNode(cur.displayText || getText(cur)));
elt.hintId = i;
}
var container = completion.options.container || ownerDocument.body;
var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
var left = pos.left, top = pos.bottom, below = true;
var offsetLeft = 0, offsetTop = 0;
if (container !== ownerDocument.body) {
// We offset the cursor position because left and top are relative to the offsetParent's top left corner.
var isContainerPositioned = ['absolute', 'relative', 'fixed'].indexOf(parentWindow.getComputedStyle(container).position) !== -1;
var offsetParent = isContainerPositioned ? container : container.offsetParent;
var offsetParentPosition = offsetParent.getBoundingClientRect();
var bodyPosition = ownerDocument.body.getBoundingClientRect();
offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft);
offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop);
}
hints.style.left = (left - offsetLeft) + "px";
hints.style.top = (top - offsetTop) + "px";
// If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
var winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth);
var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight);
container.appendChild(hints);
cm.getInputField().setAttribute("aria-autocomplete", "list")
cm.getInputField().setAttribute("aria-owns", this.id)
cm.getInputField().setAttribute("aria-activedescendant", this.id + "-" + this.selectedHint)
var box = completion.options.moveOnOverlap ? hints.getBoundingClientRect() : new DOMRect();
var scrolls = completion.options.paddingForScrollbar ? hints.scrollHeight > hints.clientHeight + 1 : false;
// Compute in the timeout to avoid reflow on init
var startScroll;
setTimeout(function() { startScroll = cm.getScrollInfo(); });
var overlapY = box.bottom - winH;
if (overlapY > 0) {
var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
if (curTop - height > 0) { // Fits above cursor
hints.style.top = (top = pos.top - height - offsetTop) + "px";
below = false;
} else if (height > winH) {
hints.style.height = (winH - 5) + "px";
hints.style.top = (top = pos.bottom - box.top - offsetTop) + "px";
var cursor = cm.getCursor();
if (data.from.ch != cursor.ch) {
pos = cm.cursorCoords(cursor);
hints.style.left = (left = pos.left - offsetLeft) + "px";
box = hints.getBoundingClientRect();
}
}
}
var overlapX = box.right - winW;
if (scrolls) overlapX += cm.display.nativeBarWidth;
if (overlapX > 0) {
if (box.right - box.left > winW) {
hints.style.width = (winW - 5) + "px";
overlapX -= (box.right - box.left) - winW;
}
hints.style.left = (left = pos.left - overlapX - offsetLeft) + "px";
}
if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
node.style.paddingRight = cm.display.nativeBarWidth + "px"
cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
setFocus: function(n) { widget.changeActive(n); },
menuSize: function() { return widget.screenAmount(); },
length: completions.length,
close: function() { completion.close(); },
pick: function() { widget.pick(); },
data: data
}));
if (completion.options.closeOnUnfocus) {
var closingOnBlur;
cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
}
cm.on("scroll", this.onScroll = function() {
var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
if (!startScroll) startScroll = cm.getScrollInfo();
var newTop = top + startScroll.top - curScroll.top;
var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop);
if (!below) point += hints.offsetHeight;
if (point <= editor.top || point >= editor.bottom) return completion.close();
hints.style.top = newTop + "px";
hints.style.left = (left + startScroll.left - curScroll.left) + "px";
});
CodeMirror.on(hints, "dblclick", function(e) {
var t = getHintElement(hints, e.target || e.srcElement);
if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
});
CodeMirror.on(hints, "click", function(e) {
var t = getHintElement(hints, e.target || e.srcElement);
if (t && t.hintId != null) {
widget.changeActive(t.hintId);
if (completion.options.completeOnSingleClick) widget.pick();
}
});
CodeMirror.on(hints, "mousedown", function() {
setTimeout(function(){cm.focus();}, 20);
});
// The first hint doesn't need to be scrolled to on init
var selectedHintRange = this.getSelectedHintRange();
if (selectedHintRange.from !== 0 || selectedHintRange.to !== 0) {
this.scrollToActive();
}
CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
return true;
}
Widget.prototype = {
close: function() {
if (this.completion.widget != this) return;
this.completion.widget = null;
if (this.hints.parentNode) this.hints.parentNode.removeChild(this.hints);
this.completion.cm.removeKeyMap(this.keyMap);
var input = this.completion.cm.getInputField()
input.removeAttribute("aria-activedescendant")
input.removeAttribute("aria-owns")
var cm = this.completion.cm;
if (this.completion.options.closeOnUnfocus) {
cm.off("blur", this.onBlur);
cm.off("focus", this.onFocus);
}
cm.off("scroll", this.onScroll);
},
disable: function() {
this.completion.cm.removeKeyMap(this.keyMap);
var widget = this;
this.keyMap = {Enter: function() { widget.picked = true; }};
this.completion.cm.addKeyMap(this.keyMap);
},
pick: function() {
this.completion.pick(this.data, this.selectedHint);
},
changeActive: function(i, avoidWrap) {
if (i >= this.data.list.length)
i = avoidWrap ? this.data.list.length - 1 : 0;
else if (i < 0)
i = avoidWrap ? 0 : this.data.list.length - 1;
if (this.selectedHint == i) return;
var node = this.hints.childNodes[this.selectedHint];
if (node) {
node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
node.removeAttribute("aria-selected")
}
node = this.hints.childNodes[this.selectedHint = i];
node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
node.setAttribute("aria-selected", "true")
this.completion.cm.getInputField().setAttribute("aria-activedescendant", node.id)
this.scrollToActive()
CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
},
scrollToActive: function() {
var selectedHintRange = this.getSelectedHintRange();
var node1 = this.hints.childNodes[selectedHintRange.from];
var node2 = this.hints.childNodes[selectedHintRange.to];
var firstNode = this.hints.firstChild;
if (node1.offsetTop < this.hints.scrollTop)
this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop;
else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
this.hints.scrollTop = node2.offsetTop + node2.offsetHeight - this.hints.clientHeight + firstNode.offsetTop;
},
screenAmount: function() {
return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
},
getSelectedHintRange: function() {
var margin = this.completion.options.scrollMargin || 0;
return {
from: Math.max(0, this.selectedHint - margin),
to: Math.min(this.data.list.length - 1, this.selectedHint + margin),
};
}
};
function applicableHelpers(cm, helpers) {
if (!cm.somethingSelected()) return helpers
var result = []
for (var i = 0; i < helpers.length; i++)
if (helpers[i].supportsSelection) result.push(helpers[i])
return result
}
function fetchHints(hint, cm, options, callback) {
if (hint.async) {
hint(cm, callback, options)
} else {
var result = hint(cm, options)
if (result && result.then) result.then(callback)
else callback(result)
}
}
function resolveAutoHints(cm, pos) {
var helpers = cm.getHelpers(pos, "hint"), words
if (helpers.length) {
var resolved = function(cm, callback, options) {
var app = applicableHelpers(cm, helpers);
function run(i) {
if (i == app.length) return callback(null)
fetchHints(app[i], cm, options, function(result) {
if (result && result.list.length > 0) callback(result)
else run(i + 1)
})
}
run(0)
}
resolved.async = true
resolved.supportsSelection = true
return resolved
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
} else if (CodeMirror.hint.anyword) {
return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
} else {
return function() {}
}
}
CodeMirror.registerHelper("hint", "auto", {
resolve: resolveAutoHints
});
CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur)
var term, from = CodeMirror.Pos(cur.line, token.start), to = cur
if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
term = token.string.substr(0, cur.ch - token.start)
} else {
term = ""
from = cur
}
var found = [];
for (var i = 0; i < options.words.length; i++) {
var word = options.words[i];
if (word.slice(0, term.length) == term)
found.push(word);
}
if (found.length) return {list: found, from: from, to: to};
});
CodeMirror.commands.autocomplete = CodeMirror.showHint;
var defaultOptions = {
hint: CodeMirror.hint.auto,
completeSingle: true,
alignWithWord: true,
closeCharacters: /[\s()\[\]{};:>,]/,
closeOnPick: true,
closeOnUnfocus: true,
updateOnCursorActivity: true,
completeOnSingleClick: true,
container: null,
customKeys: null,
extraKeys: null,
paddingForScrollbar: true,
moveOnOverlap: true,
};
CodeMirror.defineOption("hintOptions", null);
});

View File

@@ -0,0 +1,132 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var Pos = CodeMirror.Pos;
function matches(hint, typed, matchInMiddle) {
if (matchInMiddle) return hint.indexOf(typed) >= 0;
else return hint.lastIndexOf(typed, 0) == 0;
}
function getHints(cm, options) {
var tags = options && options.schemaInfo;
var quote = (options && options.quoteChar) || '"';
var matchInMiddle = options && options.matchInMiddle;
if (!tags) return;
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
if (token.end > cur.ch) {
token.end = cur.ch;
token.string = token.string.slice(0, cur.ch - token.start);
}
var inner = CodeMirror.innerMode(cm.getMode(), token.state);
if (!inner.mode.xmlCurrentTag) return
var result = [], replaceToken = false, prefix;
var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
var tagName = tag && /^\w/.test(token.string), tagStart;
if (tagName) {
var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);
var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;
if (tagType) tagStart = token.start - (tagType == "close" ? 2 : 1);
} else if (tag && token.string == "<") {
tagType = "open";
} else if (tag && token.string == "</") {
tagType = "close";
}
var tagInfo = inner.mode.xmlCurrentTag(inner.state)
if (!tag && !tagInfo || tagType) {
if (tagName)
prefix = token.string;
replaceToken = tagType;
var context = inner.mode.xmlCurrentContext ? inner.mode.xmlCurrentContext(inner.state) : []
var inner = context.length && context[context.length - 1]
var curTag = inner && tags[inner]
var childList = inner ? curTag && curTag.children : tags["!top"];
if (childList && tagType != "close") {
for (var i = 0; i < childList.length; ++i) if (!prefix || matches(childList[i], prefix, matchInMiddle))
result.push("<" + childList[i]);
} else if (tagType != "close") {
for (var name in tags)
if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || matches(name, prefix, matchInMiddle)))
result.push("<" + name);
}
if (inner && (!prefix || tagType == "close" && matches(inner, prefix, matchInMiddle)))
result.push("</" + inner + ">");
} else {
// Attribute completion
var curTag = tagInfo && tags[tagInfo.name], attrs = curTag && curTag.attrs;
var globalAttrs = tags["!attrs"];
if (!attrs && !globalAttrs) return;
if (!attrs) {
attrs = globalAttrs;
} else if (globalAttrs) { // Combine tag-local and global attributes
var set = {};
for (var nm in globalAttrs) if (globalAttrs.hasOwnProperty(nm)) set[nm] = globalAttrs[nm];
for (var nm in attrs) if (attrs.hasOwnProperty(nm)) set[nm] = attrs[nm];
attrs = set;
}
if (token.type == "string" || token.string == "=") { // A value
var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),
Pos(cur.line, token.type == "string" ? token.start : token.end));
var atName = before.match(/([^\s\u00a0=<>\"\']+)=$/), atValues;
if (!atName || !attrs.hasOwnProperty(atName[1]) || !(atValues = attrs[atName[1]])) return;
if (typeof atValues == 'function') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget
if (token.type == "string") {
prefix = token.string;
var n = 0;
if (/['"]/.test(token.string.charAt(0))) {
quote = token.string.charAt(0);
prefix = token.string.slice(1);
n++;
}
var len = token.string.length;
if (/['"]/.test(token.string.charAt(len - 1))) {
quote = token.string.charAt(len - 1);
prefix = token.string.substr(n, len - 2);
}
if (n) { // an opening quote
var line = cm.getLine(cur.line);
if (line.length > token.end && line.charAt(token.end) == quote) token.end++; // include a closing quote
}
replaceToken = true;
}
var returnHintsFromAtValues = function(atValues) {
if (atValues)
for (var i = 0; i < atValues.length; ++i) if (!prefix || matches(atValues[i], prefix, matchInMiddle))
result.push(quote + atValues[i] + quote);
return returnHints();
};
if (atValues && atValues.then) return atValues.then(returnHintsFromAtValues);
return returnHintsFromAtValues(atValues);
} else { // An attribute name
if (token.type == "attribute") {
prefix = token.string;
replaceToken = true;
}
for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || matches(attr, prefix, matchInMiddle)))
result.push(attr);
}
}
function returnHints() {
return {
list: result,
from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
to: replaceToken ? Pos(cur.line, token.end) : cur
};
}
return returnHints();
}
CodeMirror.registerHelper("hint", "xml", getHints);
});

View File

@@ -0,0 +1,349 @@
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
color: black;
direction: ltr;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre.CodeMirror-line,
.CodeMirror pre.CodeMirror-line-like {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
white-space: nowrap;
}
.CodeMirror-guttermarker { color: black; }
.CodeMirror-guttermarker-subtle { color: #999; }
/* CURSOR */
.CodeMirror-cursor {
border-left: 1px solid black;
border-right: none;
width: 0;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.cm-fat-cursor .CodeMirror-cursor {
width: auto;
border: 0 !important;
background: #7e7;
}
.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.cm-fat-cursor-mark {
background-color: rgba(20, 255, 20, 0.5);
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
}
.cm-animate-fat-cursor {
width: auto;
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
background-color: #7e7;
}
@-moz-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@-webkit-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror-overwrite .CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-rulers {
position: absolute;
left: 0; right: 0; top: -50px; bottom: 0;
overflow: hidden;
}
.CodeMirror-ruler {
border-left: 1px solid #ccc;
top: 0; bottom: 0;
position: absolute;
}
/* DEFAULT THEME */
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-strikethrough {text-decoration: line-through;}
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
.CodeMirror-composing { border-bottom: 2px solid; }
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
position: relative;
overflow: hidden;
background: white;
}
.CodeMirror-scroll {
overflow: scroll !important; /* Things will break if this is overridden */
/* 50px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -50px; margin-right: -50px;
padding-bottom: 50px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
}
.CodeMirror-sizer {
position: relative;
border-right: 50px solid transparent;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actual scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
outline: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
min-height: 100%;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
display: inline-block;
vertical-align: top;
margin-bottom: -50px;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
background: none !important;
border: none !important;
}
.CodeMirror-gutter-background {
position: absolute;
top: 0; bottom: 0;
z-index: 4;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-gutter-wrapper ::selection { background-color: transparent }
.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
.CodeMirror-lines {
cursor: text;
min-height: 1px; /* prevents collapsing before first draw */
}
.CodeMirror pre.CodeMirror-line,
.CodeMirror pre.CodeMirror-line-like {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
-webkit-tap-highlight-color: transparent;
-webkit-font-variant-ligatures: contextual;
font-variant-ligatures: contextual;
}
.CodeMirror-wrap pre.CodeMirror-line,
.CodeMirror-wrap pre.CodeMirror-line-like {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
padding: 0.1px; /* Force widget margins to stay inside of the container */
}
.CodeMirror-widget {}
.CodeMirror-rtl pre { direction: rtl; }
.CodeMirror-code {
outline: none;
}
/* Force content-box sizing for the elements where we expect it */
.CodeMirror-scroll,
.CodeMirror-sizer,
.CodeMirror-gutter,
.CodeMirror-gutters,
.CodeMirror-linenumber {
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-cursor {
position: absolute;
pointer-events: none;
}
.CodeMirror-measure pre { position: static; }
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
div.CodeMirror-dragcursors {
visibility: visible;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
.cm-searching {
background-color: #ffa;
background-color: rgba(255, 255, 0, .4);
}
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
}
}
/* See issue #2901 */
.cm-tab-wrap-hack:after { content: ''; }
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext { background: none; }

View File

@@ -0,0 +1,417 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var htmlConfig = {
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
'track': true, 'wbr': true, 'menuitem': true},
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
'th': true, 'tr': true},
contextGrabbers: {
'dd': {'dd': true, 'dt': true},
'dt': {'dd': true, 'dt': true},
'li': {'li': true},
'option': {'option': true, 'optgroup': true},
'optgroup': {'optgroup': true},
'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
'rp': {'rp': true, 'rt': true},
'rt': {'rp': true, 'rt': true},
'tbody': {'tbody': true, 'tfoot': true},
'td': {'td': true, 'th': true},
'tfoot': {'tbody': true},
'th': {'td': true, 'th': true},
'thead': {'tbody': true, 'tfoot': true},
'tr': {'tr': true}
},
doNotIndent: {"pre": true},
allowUnquoted: true,
allowMissing: true,
caseFold: true
}
var xmlConfig = {
autoSelfClosers: {},
implicitlyClosed: {},
contextGrabbers: {},
doNotIndent: {},
allowUnquoted: false,
allowMissing: false,
allowMissingTagName: false,
caseFold: false
}
CodeMirror.defineMode("xml", function(editorConf, config_) {
var indentUnit = editorConf.indentUnit
var config = {}
var defaults = config_.htmlMode ? htmlConfig : xmlConfig
for (var prop in defaults) config[prop] = defaults[prop]
for (var prop in config_) config[prop] = config_[prop]
// Return variables for tokenizers
var type, setStyle;
function inText(stream, state) {
function chain(parser) {
state.tokenize = parser;
return parser(stream, state);
}
var ch = stream.next();
if (ch == "<") {
if (stream.eat("!")) {
if (stream.eat("[")) {
if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
else return null;
} else if (stream.match("--")) {
return chain(inBlock("comment", "-->"));
} else if (stream.match("DOCTYPE", true, true)) {
stream.eatWhile(/[\w\._\-]/);
return chain(doctype(1));
} else {
return null;
}
} else if (stream.eat("?")) {
stream.eatWhile(/[\w\._\-]/);
state.tokenize = inBlock("meta", "?>");
return "meta";
} else {
type = stream.eat("/") ? "closeTag" : "openTag";
state.tokenize = inTag;
return "tag bracket";
}
} else if (ch == "&") {
var ok;
if (stream.eat("#")) {
if (stream.eat("x")) {
ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
} else {
ok = stream.eatWhile(/[\d]/) && stream.eat(";");
}
} else {
ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
}
return ok ? "atom" : "error";
} else {
stream.eatWhile(/[^&<]/);
return null;
}
}
inText.isInText = true;
function inTag(stream, state) {
var ch = stream.next();
if (ch == ">" || (ch == "/" && stream.eat(">"))) {
state.tokenize = inText;
type = ch == ">" ? "endTag" : "selfcloseTag";
return "tag bracket";
} else if (ch == "=") {
type = "equals";
return null;
} else if (ch == "<") {
state.tokenize = inText;
state.state = baseState;
state.tagName = state.tagStart = null;
var next = state.tokenize(stream, state);
return next ? next + " tag error" : "tag error";
} else if (/[\'\"]/.test(ch)) {
state.tokenize = inAttribute(ch);
state.stringStartCol = stream.column();
return state.tokenize(stream, state);
} else {
stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
return "word";
}
}
function inAttribute(quote) {
var closure = function(stream, state) {
while (!stream.eol()) {
if (stream.next() == quote) {
state.tokenize = inTag;
break;
}
}
return "string";
};
closure.isInAttribute = true;
return closure;
}
function inBlock(style, terminator) {
return function(stream, state) {
while (!stream.eol()) {
if (stream.match(terminator)) {
state.tokenize = inText;
break;
}
stream.next();
}
return style;
}
}
function doctype(depth) {
return function(stream, state) {
var ch;
while ((ch = stream.next()) != null) {
if (ch == "<") {
state.tokenize = doctype(depth + 1);
return state.tokenize(stream, state);
} else if (ch == ">") {
if (depth == 1) {
state.tokenize = inText;
break;
} else {
state.tokenize = doctype(depth - 1);
return state.tokenize(stream, state);
}
}
}
return "meta";
};
}
function lower(tagName) {
return tagName && tagName.toLowerCase();
}
function Context(state, tagName, startOfLine) {
this.prev = state.context;
this.tagName = tagName || "";
this.indent = state.indented;
this.startOfLine = startOfLine;
if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
this.noIndent = true;
}
function popContext(state) {
if (state.context) state.context = state.context.prev;
}
function maybePopContext(state, nextTagName) {
var parentTagName;
while (true) {
if (!state.context) {
return;
}
parentTagName = state.context.tagName;
if (!config.contextGrabbers.hasOwnProperty(lower(parentTagName)) ||
!config.contextGrabbers[lower(parentTagName)].hasOwnProperty(lower(nextTagName))) {
return;
}
popContext(state);
}
}
function baseState(type, stream, state) {
if (type == "openTag") {
state.tagStart = stream.column();
return tagNameState;
} else if (type == "closeTag") {
return closeTagNameState;
} else {
return baseState;
}
}
function tagNameState(type, stream, state) {
if (type == "word") {
state.tagName = stream.current();
setStyle = "tag";
return attrState;
} else if (config.allowMissingTagName && type == "endTag") {
setStyle = "tag bracket";
return attrState(type, stream, state);
} else {
setStyle = "error";
return tagNameState;
}
}
function closeTagNameState(type, stream, state) {
if (type == "word") {
var tagName = stream.current();
if (state.context && state.context.tagName != tagName &&
config.implicitlyClosed.hasOwnProperty(lower(state.context.tagName)))
popContext(state);
if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) {
setStyle = "tag";
return closeState;
} else {
setStyle = "tag error";
return closeStateErr;
}
} else if (config.allowMissingTagName && type == "endTag") {
setStyle = "tag bracket";
return closeState(type, stream, state);
} else {
setStyle = "error";
return closeStateErr;
}
}
function closeState(type, _stream, state) {
if (type != "endTag") {
setStyle = "error";
return closeState;
}
popContext(state);
return baseState;
}
function closeStateErr(type, stream, state) {
setStyle = "error";
return closeState(type, stream, state);
}
function attrState(type, _stream, state) {
if (type == "word") {
setStyle = "attribute";
return attrEqState;
} else if (type == "endTag" || type == "selfcloseTag") {
var tagName = state.tagName, tagStart = state.tagStart;
state.tagName = state.tagStart = null;
if (type == "selfcloseTag" ||
config.autoSelfClosers.hasOwnProperty(lower(tagName))) {
maybePopContext(state, tagName);
} else {
maybePopContext(state, tagName);
state.context = new Context(state, tagName, tagStart == state.indented);
}
return baseState;
}
setStyle = "error";
return attrState;
}
function attrEqState(type, stream, state) {
if (type == "equals") return attrValueState;
if (!config.allowMissing) setStyle = "error";
return attrState(type, stream, state);
}
function attrValueState(type, stream, state) {
if (type == "string") return attrContinuedState;
if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;}
setStyle = "error";
return attrState(type, stream, state);
}
function attrContinuedState(type, stream, state) {
if (type == "string") return attrContinuedState;
return attrState(type, stream, state);
}
return {
startState: function(baseIndent) {
var state = {tokenize: inText,
state: baseState,
indented: baseIndent || 0,
tagName: null, tagStart: null,
context: null}
if (baseIndent != null) state.baseIndent = baseIndent
return state
},
token: function(stream, state) {
if (!state.tagName && stream.sol())
state.indented = stream.indentation();
if (stream.eatSpace()) return null;
type = null;
var style = state.tokenize(stream, state);
if ((style || type) && style != "comment") {
setStyle = null;
state.state = state.state(type || style, stream, state);
if (setStyle)
style = setStyle == "error" ? style + " error" : setStyle;
}
return style;
},
indent: function(state, textAfter, fullLine) {
var context = state.context;
// Indent multi-line strings (e.g. css).
if (state.tokenize.isInAttribute) {
if (state.tagStart == state.indented)
return state.stringStartCol + 1;
else
return state.indented + indentUnit;
}
if (context && context.noIndent) return CodeMirror.Pass;
if (state.tokenize != inTag && state.tokenize != inText)
return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
// Indent the starts of attribute names.
if (state.tagName) {
if (config.multilineTagIndentPastTag !== false)
return state.tagStart + state.tagName.length + 2;
else
return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1);
}
if (config.alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
if (tagAfter && tagAfter[1]) { // Closing tag spotted
while (context) {
if (context.tagName == tagAfter[2]) {
context = context.prev;
break;
} else if (config.implicitlyClosed.hasOwnProperty(lower(context.tagName))) {
context = context.prev;
} else {
break;
}
}
} else if (tagAfter) { // Opening tag spotted
while (context) {
var grabbers = config.contextGrabbers[lower(context.tagName)];
if (grabbers && grabbers.hasOwnProperty(lower(tagAfter[2])))
context = context.prev;
else
break;
}
}
while (context && context.prev && !context.startOfLine)
context = context.prev;
if (context) return context.indent + indentUnit;
else return state.baseIndent || 0;
},
electricInput: /<\/[\s\w:]+>$/,
blockCommentStart: "<!--",
blockCommentEnd: "-->",
configuration: config.htmlMode ? "html" : "xml",
helperType: config.htmlMode ? "html" : "xml",
skipAttribute: function(state) {
if (state.state == attrValueState)
state.state = attrState
},
xmlCurrentTag: function(state) {
return state.tagName ? {name: state.tagName, close: state.type == "closeTag"} : null
},
xmlCurrentContext: function(state) {
var context = []
for (var cx = state.context; cx; cx = cx.prev)
context.push(cx.tagName)
return context.reverse()
}
};
});
CodeMirror.defineMIME("text/xml", "xml");
CodeMirror.defineMIME("application/xml", "xml");
if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
});

View File

@@ -0,0 +1,135 @@
/*
Name: material
Author: Mattia Astorino (http://github.com/equinusocio)
Website: https://material-theme.site/
*/
.cm-s-material-darker.CodeMirror {
background-color: #212121;
color: #EEFFFF;
}
.cm-s-material-darker .CodeMirror-gutters {
background: #212121;
color: #545454;
border: none;
}
.cm-s-material-darker .CodeMirror-guttermarker,
.cm-s-material-darker .CodeMirror-guttermarker-subtle,
.cm-s-material-darker .CodeMirror-linenumber {
color: #545454;
}
.cm-s-material-darker .CodeMirror-cursor {
border-left: 1px solid #FFCC00;
}
.cm-s-material-darker div.CodeMirror-selected {
background: rgba(97, 97, 97, 0.2);
}
.cm-s-material-darker.CodeMirror-focused div.CodeMirror-selected {
background: rgba(97, 97, 97, 0.2);
}
.cm-s-material-darker .CodeMirror-line::selection,
.cm-s-material-darker .CodeMirror-line>span::selection,
.cm-s-material-darker .CodeMirror-line>span>span::selection {
background: rgba(128, 203, 196, 0.2);
}
.cm-s-material-darker .CodeMirror-line::-moz-selection,
.cm-s-material-darker .CodeMirror-line>span::-moz-selection,
.cm-s-material-darker .CodeMirror-line>span>span::-moz-selection {
background: rgba(128, 203, 196, 0.2);
}
.cm-s-material-darker .CodeMirror-activeline-background {
background: rgba(0, 0, 0, 0.5);
}
.cm-s-material-darker .cm-keyword {
color: #C792EA;
}
.cm-s-material-darker .cm-operator {
color: #89DDFF;
}
.cm-s-material-darker .cm-variable-2 {
color: #EEFFFF;
}
.cm-s-material-darker .cm-variable-3,
.cm-s-material-darker .cm-type {
color: #f07178;
}
.cm-s-material-darker .cm-builtin {
color: #FFCB6B;
}
.cm-s-material-darker .cm-atom {
color: #F78C6C;
}
.cm-s-material-darker .cm-number {
color: #FF5370;
}
.cm-s-material-darker .cm-def {
color: #82AAFF;
}
.cm-s-material-darker .cm-string {
color: #C3E88D;
}
.cm-s-material-darker .cm-string-2 {
color: #f07178;
}
.cm-s-material-darker .cm-comment {
color: #545454;
}
.cm-s-material-darker .cm-variable {
color: #f07178;
}
.cm-s-material-darker .cm-tag {
color: #FF5370;
}
.cm-s-material-darker .cm-meta {
color: #FFCB6B;
}
.cm-s-material-darker .cm-attribute {
color: #C792EA;
}
.cm-s-material-darker .cm-property {
color: #C792EA;
}
.cm-s-material-darker .cm-qualifier {
color: #DECB6B;
}
.cm-s-material-darker .cm-variable-3,
.cm-s-material-darker .cm-type {
color: #DECB6B;
}
.cm-s-material-darker .cm-error {
color: rgba(255, 255, 255, 1.0);
background-color: #FF5370;
}
.cm-s-material-darker .CodeMirror-matchingbracket {
text-decoration: underline;
color: white !important;
}

View File

@@ -0,0 +1,42 @@
/* Based on arcticicestudio's Nord theme */
/* https://github.com/arcticicestudio/nord */
.cm-s-nord.CodeMirror { background: #2e3440; color: #d8dee9; }
.cm-s-nord div.CodeMirror-selected { background: #434c5e; }
.cm-s-nord .CodeMirror-line::selection, .cm-s-nord .CodeMirror-line > span::selection, .cm-s-nord .CodeMirror-line > span > span::selection { background: #3b4252; }
.cm-s-nord .CodeMirror-line::-moz-selection, .cm-s-nord .CodeMirror-line > span::-moz-selection, .cm-s-nord .CodeMirror-line > span > span::-moz-selection { background: #3b4252; }
.cm-s-nord .CodeMirror-gutters { background: #2e3440; border-right: 0px; }
.cm-s-nord .CodeMirror-guttermarker { color: #4c566a; }
.cm-s-nord .CodeMirror-guttermarker-subtle { color: #4c566a; }
.cm-s-nord .CodeMirror-linenumber { color: #4c566a; }
.cm-s-nord .CodeMirror-cursor { border-left: 1px solid #f8f8f0; }
.cm-s-nord span.cm-comment { color: #4c566a; }
.cm-s-nord span.cm-atom { color: #b48ead; }
.cm-s-nord span.cm-number { color: #b48ead; }
.cm-s-nord span.cm-comment.cm-attribute { color: #97b757; }
.cm-s-nord span.cm-comment.cm-def { color: #bc9262; }
.cm-s-nord span.cm-comment.cm-tag { color: #bc6283; }
.cm-s-nord span.cm-comment.cm-type { color: #5998a6; }
.cm-s-nord span.cm-property, .cm-s-nord span.cm-attribute { color: #8FBCBB; }
.cm-s-nord span.cm-keyword { color: #81A1C1; }
.cm-s-nord span.cm-builtin { color: #81A1C1; }
.cm-s-nord span.cm-string { color: #A3BE8C; }
.cm-s-nord span.cm-variable { color: #d8dee9; }
.cm-s-nord span.cm-variable-2 { color: #d8dee9; }
.cm-s-nord span.cm-variable-3, .cm-s-nord span.cm-type { color: #d8dee9; }
.cm-s-nord span.cm-def { color: #8FBCBB; }
.cm-s-nord span.cm-bracket { color: #81A1C1; }
.cm-s-nord span.cm-tag { color: #bf616a; }
.cm-s-nord span.cm-header { color: #b48ead; }
.cm-s-nord span.cm-link { color: #b48ead; }
.cm-s-nord span.cm-error { background: #bf616a; color: #f8f8f0; }
.cm-s-nord .CodeMirror-activeline-background { background: #3b4252; }
.cm-s-nord .CodeMirror-matchingbracket {
text-decoration: underline;
color: white !important;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,78 @@
/*! `javascript` grammar compiled for Highlight.js 11.7.0 */
(()=>{var e=(()=>{"use strict"
;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","module","global"],i=[].concat(r,t,s)
;return o=>{const l=o.regex,b=e,d={begin:/<[A-Za-z0-9\\._:-]+/,
end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{
const a=e[0].length+e.index,t=e.input[a]
;if("<"===t||","===t)return void n.ignoreMatch();let s
;">"===t&&(((e,{after:n})=>{const a="</"+e[0].slice(1)
;return-1!==e.input.indexOf(a,n)})(e,{after:a})||n.ignoreMatch())
;const r=e.input.substring(a)
;((s=r.match(/^\s*=/))||(s=r.match(/^\s+extends\s+/))&&0===s.index)&&n.ignoreMatch()
}},g={$pattern:e,keyword:n,literal:a,built_in:i,"variable.language":c
},u="\\.([0-9](_?[0-9])*)",m="0|[1-9](_?[0-9])*|0[0-7]*[89][0-9]*",E={
className:"number",variants:[{
begin:`(\\b(${m})((${u})|\\.)?|(${u}))[eE][+-]?([0-9](_?[0-9])*)\\b`},{
begin:`\\b(${m})\\b((${u})\\b|\\.)?|(${u})\\b`},{
begin:"\\b(0|[1-9](_?[0-9])*)n\\b"},{
begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?\\b"},{
begin:"\\b0[bB][0-1](_?[0-1])*n?\\b"},{begin:"\\b0[oO][0-7](_?[0-7])*n?\\b"},{
begin:"\\b0[0-7]+n?\\b"}],relevance:0},A={className:"subst",begin:"\\$\\{",
end:"\\}",keywords:g,contains:[]},y={begin:"html`",end:"",starts:{end:"`",
returnEnd:!1,contains:[o.BACKSLASH_ESCAPE,A],subLanguage:"xml"}},N={
begin:"css`",end:"",starts:{end:"`",returnEnd:!1,
contains:[o.BACKSLASH_ESCAPE,A],subLanguage:"css"}},_={className:"string",
begin:"`",end:"`",contains:[o.BACKSLASH_ESCAPE,A]},h={className:"comment",
variants:[o.COMMENT(/\/\*\*(?!\/)/,"\\*/",{relevance:0,contains:[{
begin:"(?=@[A-Za-z]+)",relevance:0,contains:[{className:"doctag",
begin:"@[A-Za-z]+"},{className:"type",begin:"\\{",end:"\\}",excludeEnd:!0,
excludeBegin:!0,relevance:0},{className:"variable",begin:b+"(?=\\s*(-)|$)",
endsParent:!0,relevance:0},{begin:/(?=[^\n])\s/,relevance:0}]}]
}),o.C_BLOCK_COMMENT_MODE,o.C_LINE_COMMENT_MODE]
},f=[o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,y,N,_,{match:/\$\d+/},E]
;A.contains=f.concat({begin:/\{/,end:/\}/,keywords:g,contains:["self"].concat(f)
});const v=[].concat(h,A.contains),p=v.concat([{begin:/\(/,end:/\)/,keywords:g,
contains:["self"].concat(v)}]),S={className:"params",begin:/\(/,end:/\)/,
excludeBegin:!0,excludeEnd:!0,keywords:g,contains:p},w={variants:[{
match:[/class/,/\s+/,b,/\s+/,/extends/,/\s+/,l.concat(b,"(",l.concat(/\./,b),")*")],
scope:{1:"keyword",3:"title.class",5:"keyword",7:"title.class.inherited"}},{
match:[/class/,/\s+/,b],scope:{1:"keyword",3:"title.class"}}]},R={relevance:0,
match:l.either(/\bJSON/,/\b[A-Z][a-z]+([A-Z][a-z]*|\d)*/,/\b[A-Z]{2,}([A-Z][a-z]+|\d)+([A-Z][a-z]*)*/,/\b[A-Z]{2,}[a-z]+([A-Z][a-z]+|\d)*([A-Z][a-z]*)*/),
className:"title.class",keywords:{_:[...t,...s]}},O={variants:[{
match:[/function/,/\s+/,b,/(?=\s*\()/]},{match:[/function/,/\s*(?=\()/]}],
className:{1:"keyword",3:"title.function"},label:"func.def",contains:[S],
illegal:/%/},k={
match:l.concat(/\b/,(I=[...r,"super","import"],l.concat("(?!",I.join("|"),")")),b,l.lookahead(/\(/)),
className:"title.function",relevance:0};var I;const x={
begin:l.concat(/\./,l.lookahead(l.concat(b,/(?![0-9A-Za-z$_(])/))),end:b,
excludeBegin:!0,keywords:"prototype",className:"property",relevance:0},T={
match:[/get|set/,/\s+/,b,/(?=\()/],className:{1:"keyword",3:"title.function"},
contains:[{begin:/\(\)/},S]
},C="(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|"+o.UNDERSCORE_IDENT_RE+")\\s*=>",M={
match:[/const|var|let/,/\s+/,b,/\s*/,/=\s*/,/(async\s*)?/,l.lookahead(C)],
keywords:"async",className:{1:"keyword",3:"title.function"},contains:[S]}
;return{name:"Javascript",aliases:["js","jsx","mjs","cjs"],keywords:g,exports:{
PARAMS_CONTAINS:p,CLASS_REFERENCE:R},illegal:/#(?![$_A-z])/,
contains:[o.SHEBANG({label:"shebang",binary:"node",relevance:5}),{
label:"use_strict",className:"meta",relevance:10,
begin:/^\s*['"]use (strict|asm)['"]/
},o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,y,N,_,h,{match:/\$\d+/},E,R,{
className:"attr",begin:b+l.lookahead(":"),relevance:0},M,{
begin:"("+o.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",
keywords:"return throw case",relevance:0,contains:[h,o.REGEXP_MODE,{
className:"function",begin:C,returnBegin:!0,end:"\\s*=>",contains:[{
className:"params",variants:[{begin:o.UNDERSCORE_IDENT_RE,relevance:0},{
className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,
excludeEnd:!0,keywords:g,contains:p}]}]},{begin:/,/,relevance:0},{match:/\s+/,
relevance:0},{variants:[{begin:"<>",end:"</>"},{
match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:d.begin,
"on:begin":d.isTrulyOpeningTag,end:d.end}],subLanguage:"xml",contains:[{
begin:d.begin,end:d.end,skip:!0,contains:["self"]}]}]},O,{
beginKeywords:"while if switch catch for"},{
begin:"\\b(?!function)"+o.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{",
returnBegin:!0,label:"func.def",contains:[S,o.inherit(o.TITLE_MODE,{begin:b,
className:"title.function"})]},{match:/\.\.\./,relevance:0},x,{match:"\\$"+b,
relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"},
contains:[S]},k,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,
className:"variable.constant"},w,T,{match:/\$[(.]/}]}}})()
;hljs.registerLanguage("javascript",e)})();

View File

@@ -0,0 +1,41 @@
/*! `python` grammar compiled for Highlight.js 11.7.0 */
(()=>{var e=(()=>{"use strict";return e=>{
const n=e.regex,a=/[\p{XID_Start}_]\p{XID_Continue}*/u,i=["and","as","assert","async","await","break","case","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","match","nonlocal|10","not","or","pass","raise","return","try","while","with","yield"],s={
$pattern:/[A-Za-z]\w+|__\w+__/,keyword:i,
built_in:["__import__","abs","all","any","ascii","bin","bool","breakpoint","bytearray","bytes","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","exec","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","print","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip"],
literal:["__debug__","Ellipsis","False","None","NotImplemented","True"],
type:["Any","Callable","Coroutine","Dict","List","Literal","Generic","Optional","Sequence","Set","Tuple","Type","Union"]
},t={className:"meta",begin:/^(>>>|\.\.\.) /},r={className:"subst",begin:/\{/,
end:/\}/,keywords:s,illegal:/#/},l={begin:/\{\{/,relevance:0},b={
className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{
begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/,
contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{
begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/,
contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{
begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/,
contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/,
end:/"""/,contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([uU]|[rR])'/,end:/'/,
relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{
begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/,
end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/,
contains:[e.BACKSLASH_ESCAPE,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/,
contains:[e.BACKSLASH_ESCAPE,l,r]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]
},o="[0-9](_?[0-9])*",c=`(\\b(${o}))?\\.(${o})|\\b(${o})\\.`,d="\\b|"+i.join("|"),g={
className:"number",relevance:0,variants:[{
begin:`(\\b(${o})|(${c}))[eE][+-]?(${o})[jJ]?(?=${d})`},{begin:`(${c})[jJ]?`},{
begin:`\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${d})`},{
begin:`\\b0[bB](_?[01])+[lL]?(?=${d})`},{begin:`\\b0[oO](_?[0-7])+[lL]?(?=${d})`
},{begin:`\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${d})`},{begin:`\\b(${o})[jJ](?=${d})`
}]},p={className:"comment",begin:n.lookahead(/# type:/),end:/$/,keywords:s,
contains:[{begin:/# type:/},{begin:/#/,end:/\b\B/,endsWithParent:!0}]},m={
className:"params",variants:[{className:"",begin:/\(\s*\)/,skip:!0},{begin:/\(/,
end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:s,
contains:["self",t,g,b,e.HASH_COMMENT_MODE]}]};return r.contains=[b,g,t],{
name:"Python",aliases:["py","gyp","ipython"],unicodeRegex:!0,keywords:s,
illegal:/(<\/|->|\?)|=>/,contains:[t,g,{begin:/\bself\b/},{beginKeywords:"if",
relevance:0},b,p,e.HASH_COMMENT_MODE,{match:[/\bdef/,/\s+/,a],scope:{
1:"keyword",3:"title.function"},contains:[m]},{variants:[{
match:[/\bclass/,/\s+/,a,/\s*/,/\(\s*/,a,/\s*\)/]},{match:[/\bclass/,/\s+/,a]}],
scope:{1:"keyword",3:"title.class",6:"title.class.inherited"}},{
className:"meta",begin:/^[\t ]*@/,end:/(?=#)|$/,contains:[g,m,b]}]}}})()
;hljs.registerLanguage("python",e)})();

View File

@@ -0,0 +1,10 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
Theme: GitHub
Description: Light theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Outdated base version: https://github.com/primer/github-syntax-light
Current colors taken from GitHub's CSS
*/.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#005cc5}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-code,.hljs-comment,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}

View File

@@ -0,0 +1,118 @@
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em
}
code.hljs {
padding: 3px 5px
}
/*!
Theme: GitHub Dark
Description: Dark theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Outdated base version: https://github.com/primer/github-syntax-dark
Current colors taken from GitHub's CSS
*/
.hljs {
color: #c9d1d9;
background: #0d1117
}
.hljs-doctag,
.hljs-keyword,
.hljs-meta .hljs-keyword,
.hljs-template-tag,
.hljs-template-variable,
.hljs-type,
.hljs-variable.language_ {
/* prettylights-syntax-keyword */
color: #ff7b72
}
.hljs-title,
.hljs-title.class_,
.hljs-title.class_.inherited__,
.hljs-title.function_ {
/* prettylights-syntax-entity */
color: #d2a8ff
}
.hljs-attr,
.hljs-attribute,
.hljs-literal,
.hljs-meta,
.hljs-number,
.hljs-operator,
.hljs-variable,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-id {
/* prettylights-syntax-constant */
color: #79c0ff
}
.hljs-regexp,
.hljs-string,
.hljs-meta .hljs-string {
/* prettylights-syntax-string */
color: #a5d6ff
}
.hljs-built_in,
.hljs-symbol {
/* prettylights-syntax-variable */
color: #ffa657
}
.hljs-comment,
.hljs-code,
.hljs-formula {
/* prettylights-syntax-comment */
color: #8b949e
}
.hljs-name,
.hljs-quote,
.hljs-selector-tag,
.hljs-selector-pseudo {
/* prettylights-syntax-entity-tag */
color: #7ee787
}
.hljs-subst {
/* prettylights-syntax-storage-modifier-import */
color: #c9d1d9
}
.hljs-section {
/* prettylights-syntax-markup-heading */
color: #1f6feb;
font-weight: bold
}
.hljs-bullet {
/* prettylights-syntax-markup-list */
color: #f2cc60
}
.hljs-emphasis {
/* prettylights-syntax-markup-italic */
color: #c9d1d9;
font-style: italic
}
.hljs-strong {
/* prettylights-syntax-markup-bold */
color: #c9d1d9;
font-weight: bold
}
.hljs-addition {
/* prettylights-syntax-markup-inserted */
color: #aff5b4;
background-color: #033a16
}
.hljs-deletion {
/* prettylights-syntax-markup-deleted */
color: #ffdcd7;
background-color: #67060c
}
.hljs-char.escape_,
.hljs-link,
.hljs-params,
.hljs-property,
.hljs-punctuation,
.hljs-tag {
/* purposely ignored */
}

View File

@@ -0,0 +1,107 @@
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em
}
code.hljs {
padding: 3px 5px
}
/*
Intellij-light style (c) Pegasis <me@pegasis.site>
*/
.hljs {
color: #000;
background: #fff
}
.hljs-subst,
.hljs-title {
font-weight: normal;
color: #000
}
.hljs-title.function_ {
color: #7A7A43
}
.hljs-code,
.hljs-comment,
.hljs-quote {
color: #8C8C8C;
font-style: italic
}
.hljs-meta {
color: #9E880D
}
.hljs-section {
color: #871094
}
.hljs-variable.language_,
.hljs-symbol,
.hljs-selector-class,
.hljs-selector-id,
.hljs-selector-tag,
.hljs-template-tag,
.hljs-selector-attr,
.hljs-selector-pseudo,
.hljs-keyword,
.hljs-meta .hljs-keyword,
.hljs-literal,
.hljs-name,
.hljs-built_in,
.hljs-type {
color: #0033B3
}
.hljs-property,
.hljs-attr {
color: #871094
}
.hljs-attribute {
color: #174AD4
}
.hljs-number {
color: #1750EB
}
.hljs-regexp {
color: #264EFF
}
.hljs-link {
text-decoration: underline;
color: #006DCC
}
.hljs-meta .hljs-string,
.hljs-string {
color: #067D17
}
.hljs-char.escape_ {
color: #0037A6
}
.hljs-doctag {
text-decoration: underline
}
.hljs-template-variable {
color: #248F8F
}
.hljs-addition {
background: #BEE6BE
}
.hljs-deletion {
background: #D6D6D6
}
.hljs-emphasis {
font-style: italic
}
.hljs-strong {
font-weight: bold
}
.hljs-variable,
.hljs-operator,
.hljs-punctuation,
.hljs-title.class_.inherited__,
.hljs-title.class_,
.hljs-params,
.hljs-bullet,
.hljs-formula,
.hljs-tag {
/* purposely ignored */
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
library/QQDecryption.dll Normal file

Binary file not shown.

BIN
library/UnlockQQ.exe Normal file

Binary file not shown.

BIN
libs/JNC-1.0-jnc.jar Normal file

Binary file not shown.

View File

@@ -0,0 +1,162 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{c4fa048f-df39-48ab-a261-c40dfedaecee}</ProjectGuid>
<RootNamespace>QQDecryption</RootNamespace>
<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>C:\Users\Administrator\.jdks\corretto-20.0.2.1\include\win32;C:\Users\Administrator\.jdks\corretto-20.0.2.1\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;QQDECRYPTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;QQDECRYPTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;QQDECRYPTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;QQDECRYPTION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="framework.h" />
<ClInclude Include="org_QQdecryption_QQMusicAutoDecryptor.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="org_QQdecryption_QQMusicAutoDecryptor.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="org_QQdecryption_QQMusicAutoDecryptor.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="org_QQdecryption_QQMusicAutoDecryptor.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>false</ShowAllFiles>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,60 @@
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
HMODULE hInjectedModule = 0;
// 修改后的导出函数定义(接受两个独立参数)
extern "C" __declspec(dllexport) void __stdcall RemoteDecrypt(LPVOID lpParam) {
DecryptParams* pParams = static_cast<DecryptParams*>(lpParam);
// 直接使用 params.src 和 params.dst
const wchar_t* src = pParams->src;
const wchar_t* dst = pParams->dst;
// 加载QQMusicCommon.dll函数
HMODULE hLib = LoadLibraryW(L"QQMusicCommon.dll");
if (!hLib) return;
typedef void* (__thiscall* EncConstructor)(void*);
typedef void(__thiscall* EncDestructor)(void*);
typedef BOOL(__thiscall* EncOpen)(void*, const wchar_t*, BOOL, BOOL);
typedef DWORD(__thiscall* EncGetSize)(void*);
typedef DWORD(__thiscall* EncRead)(void*, BYTE*, DWORD, __int64);
EncConstructor pConstructor = (EncConstructor)GetProcAddress(hLib, "??0EncAndDesMediaFile@@QAE@XZ");
EncDestructor pDestructor = (EncDestructor)GetProcAddress(hLib, "??1EncAndDesMediaFile@@QAE@XZ");
EncOpen pOpen = (EncOpen)GetProcAddress(hLib, "?Open@EncAndDesMediaFile@@QAE_NPB_W_N1@Z");
EncGetSize pGetSize = (EncGetSize)GetProcAddress(hLib, "?GetSize@EncAndDesMediaFile@@QAEKXZ");
EncRead pRead = (EncRead)GetProcAddress(hLib, "?Read@EncAndDesMediaFile@@QAEKPAEK_J@Z");
if (!pConstructor || !pDestructor || !pOpen || !pGetSize || !pRead) {
FreeLibrary(hLib);
return;
}
// 执行解密
BYTE obj[0x28] = { 0 };
pConstructor(obj);
if (pOpen(obj, src, TRUE, FALSE)) {
DWORD size = pGetSize(obj);
BYTE* buffer = new BYTE[size];
if (pRead(obj, buffer, size, 0) == size) {
std::ofstream out(dst, std::ios::binary);
out.write(reinterpret_cast<char*>(buffer), size);
out.close();
}
delete[] buffer;
}
pDestructor(obj);
FreeLibrary(hLib);
}
// DLL入口点
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
// 可选:自动解密示例文件(需根据实际路径调整)
// DecryptFileInProcess(L"C:\\Music\\encrypted.mflac", L"C:\\Music\\decrypted.flac");
hInjectedModule = hModule;
}
return TRUE;
}

View File

@@ -0,0 +1,5 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
// Windows 头文件
#include <windows.h>

View File

@@ -0,0 +1,156 @@
#include "pch.h"
#include <iostream>
#include <windows.h>
#include <tlhelp32.h>
#include <string>
// <20><><EFBFBD><EFBFBD><E5B5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD><EFBFBD><EFBFBD>DLL<4C><4C>ʵ<EFBFBD>֣<EFBFBD>
typedef void(__stdcall* RemoteDecryptFunc)(LPVOID lpParam);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>QQ<51><51><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>PID
DWORD FindQQMusicPID() {
PROCESSENTRY32W pe32 = { sizeof(PROCESSENTRY32W) };
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
DWORD pid = 0;
if (Process32FirstW(hSnapshot, &pe32)) {
do {
if (wcscmp(pe32.szExeFile, L"QQMusic.exe") == 0) {
pid = pe32.th32ProcessID;
break;
}
} while (Process32NextW(hSnapshot, &pe32));
}
CloseHandle(hSnapshot);
return pid;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>DLL<4C><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>̺<EFBFBD><CCBA><EFBFBD>
bool InjectAndCallDecrypt(DWORD pid, const wchar_t* src, const wchar_t* dst) {
// <20><>ȡ<EFBFBD><C8A1>ǰDLL·<4C><C2B7><EFBFBD><EFBFBD>ʹ<EFBFBD>õ<EFBFBD>ǰģ<C7B0><C4A3><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7>
wchar_t dllPath[MAX_PATH] = { 0 };
HMODULE hCurrentModule = NULL;
// ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7>ȡ<EFBFBD><C8A1>ǰģ<C7B0><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (!GetModuleHandleExW(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCWSTR)&InjectAndCallDecrypt, // <20><><EFBFBD>⵱ǰģ<C7B0><C4A3><EFBFBD>еĵ<D0B5>ַ
&hCurrentModule
)) {
return false;
}
GetModuleFileNameW(hCurrentModule, dllPath, MAX_PATH);
// <20><><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!hProcess) return false;
// <20><><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>д<EFBFBD><D0B4>DLL·<4C><C2B7>
SIZE_T pathSize = (wcslen(dllPath) + 1) * sizeof(wchar_t);
LPVOID pRemoteDllPath = VirtualAllocEx(hProcess, NULL, pathSize, MEM_COMMIT, PAGE_READWRITE);
if (!pRemoteDllPath || !WriteProcessMemory(hProcess, pRemoteDllPath, dllPath, pathSize, NULL)) {
CloseHandle(hProcess);
return false;
}
// ע<><D7A2>DLL
HANDLE hThread = CreateRemoteThread(
hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW"),
pRemoteDllPath,
0,
NULL
);
if (!hThread) {
VirtualFreeEx(hProcess, pRemoteDllPath, 0, MEM_RELEASE);
CloseHandle(hProcess);
return false;
}
WaitForSingleObject(hThread, INFINITE);
// <20><>ȡע<C8A1><D7A2><EFBFBD><EFBFBD>DLL<4C><4C>ַ
DWORD_PTR dllBaseAddr = 0;
GetExitCodeThread(hThread, (LPDWORD)&dllBaseAddr);
CloseHandle(hThread);
// <20><><EFBFBD><EFBFBD>Զ<EFBFBD>̺<EFBFBD><CCBA><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>ؼ<EFBFBD><D8BC>޸IJ<DEB8><C4B2>֣<EFBFBD>
// <20><><EFBFBD><EFBFBD>1<EFBFBD><31><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>غ<EFBFBD><D8BA><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ַ
HMODULE hLocalModule = GetModuleHandleW(dllPath); // <20><><EFBFBD>ص<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD>ͬDLL
if (!hLocalModule) {
VirtualFreeEx(hProcess, pRemoteDllPath, 0, MEM_RELEASE);
CloseHandle(hProcess);
return false;
}
// <20><><EFBFBD><EFBFBD>2<EFBFBD><32><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD>еĵ<D0B5>ַ<EFBFBD><D6B7>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RemoteDecryptFunc pLocalFunc = (RemoteDecryptFunc)GetProcAddress(hLocalModule,
#ifdef _WIN32
"_RemoteDecrypt@4" // 32λ<32><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#else
"RemoteDecrypt" // 64λ<34><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#endif
);
if (!pLocalFunc) {
VirtualFreeEx(hProcess, pRemoteDllPath, 0, MEM_RELEASE);
CloseHandle(hProcess);
return false;
}
// <20><><EFBFBD><EFBFBD>3<EFBFBD><33><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3BAAF>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD>
DWORD_PTR funcOffset = (DWORD_PTR)pLocalFunc - (DWORD_PTR)hLocalModule;
// <20><><EFBFBD><EFBFBD>4<EFBFBD><34><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>̺<EFBFBD><CCBA><EFBFBD><EFBFBD><EFBFBD>ַ
RemoteDecryptFunc pRemoteFunc = (RemoteDecryptFunc)(dllBaseAddr + funcOffset);
// ׼<><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
DecryptParams localParams = { 0 };
wcscpy_s(localParams.src, MAX_PATH, src);
wcscpy_s(localParams.dst, MAX_PATH, dst);
// <20><>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
LPVOID pRemoteParams = VirtualAllocEx(hProcess, NULL, sizeof(DecryptParams), MEM_COMMIT, PAGE_READWRITE);
if (!pRemoteParams || !WriteProcessMemory(hProcess, pRemoteParams, &localParams, sizeof(DecryptParams), NULL)) {
VirtualFreeEx(hProcess, pRemoteDllPath, 0, MEM_RELEASE);
CloseHandle(hProcess);
return false;
}
// <20><><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>̵߳<DFB3><CCB5>ý<EFBFBD><C3BD>ܺ<EFBFBD><DCBA><EFBFBD>
hThread = CreateRemoteThread(
hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)pRemoteFunc,
pRemoteParams,
0,
NULL
);
if (!hThread) {
VirtualFreeEx(hProcess, pRemoteParams, 0, MEM_RELEASE);
VirtualFreeEx(hProcess, pRemoteDllPath, 0, MEM_RELEASE);
CloseHandle(hProcess);
return false;
}
// <20>ȴ<EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
WaitForSingleObject(hThread, INFINITE);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
VirtualFreeEx(hProcess, pRemoteDllPath, 0, MEM_RELEASE);
VirtualFreeEx(hProcess, pRemoteParams, 0, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
return true;
}
extern "C" __declspec(dllexport) void Execute(const wchar_t* src, const wchar_t* dst)
{
InjectAndCallDecrypt(FindQQMusicPID(), src, dst);
}

View File

@@ -0,0 +1,21 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_QQdecryption_QQMusicAutoDecryptor */
#ifndef _Included_org_QQdecryption_QQMusicAutoDecryptor
#define _Included_org_QQdecryption_QQMusicAutoDecryptor
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_QQdecryption_QQMusicAutoDecryptor
* Method: decrypt
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_QQdecryption_QQMusicAutoDecryptor_decrypt
(JNIEnv *, jclass, jstring, jstring);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,5 @@
// pch.cpp: 与预编译标头对应的源文件
#include "pch.h"
// 当使用预编译的头时,需要使用此源文件,编译才能成功。

View File

@@ -0,0 +1,45 @@
// pch.h: 这是预编译标头文件。
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。
#ifndef PCH_H
#define PCH_H
// 添加要在此处预编译的标头
#include "framework.h"
#include <windows.h>
#include <string>
#include <fstream>
#pragma pack(push, 1)
struct DecryptParams {
wchar_t src[MAX_PATH]; // 源文件路径
wchar_t dst[MAX_PATH]; // 目标文件路径
};
#pragma pack(pop)
// 导出函数声明
extern "C" __declspec(dllexport) void __stdcall RemoteDecrypt(LPVOID lpParam);
// 目标DLL函数声明
typedef void* (__thiscall* EncConstructor)(void* thisPtr);
typedef void(__thiscall* EncDestructor)(void* thisPtr);
typedef BOOL(__thiscall* EncOpen)(void* thisPtr, const wchar_t* path, BOOL a1, BOOL a2);
typedef DWORD(__thiscall* EncGetSize)(void* thisPtr);
typedef DWORD(__thiscall* EncRead)(void* thisPtr, BYTE* buf, DWORD size, __int64 offset);
// 全局函数指针
extern EncConstructor pConstructor;
extern EncDestructor pDestructor;
extern EncOpen pOpen;
extern EncGetSize pGetSize;
extern EncRead pRead;
extern HMODULE hTargetDll;
extern HMODULE hInjectedModule;
#endif //PCH_H

View File

@@ -0,0 +1,49 @@
#include <iostream>
#include <Windows.h>
#include <io.h>
#include <fcntl.h>
// DLL function declaration
extern "C" __declspec(dllimport) void Execute(const wchar_t* src, const wchar_t* dst);
// Set console to UTF-8 mode
void SetConsoleUTF8() {
_setmode(_fileno(stdout), _O_U8TEXT);
_setmode(_fileno(stderr), _O_U8TEXT);
SetConsoleOutputCP(CP_UTF8);
}
int wmain(int argc, wchar_t* argv[]) {
// Initialize console encoding
SetConsoleUTF8();
if (argc != 3) {
std::wcerr << L"Usage: " << argv[0]
<< L" <source_path> <destination_path>" << std::endl;
return 1;
}
// Verify parameters
std::wstring src(argv[1]);
std::wstring dst(argv[2]);
try {
// Debug output
std::wcout << L"Processing file:\nSource: " << src
<< L"\nDestination: " << dst << std::endl;
// Call DLL function
Execute(src.c_str(), dst.c_str());
std::wcout << L"Operation completed successfully!" << std::endl;
return 0;
}
catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 2;
}
catch (...) {
std::cerr << "Unknown error occurred!" << std::endl;
return 3;
}
}

View File

@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{5f9e6925-65ba-4c62-839c-7ceb7c735e2b}</ProjectGuid>
<RootNamespace>UnlockQQ</RootNamespace>
<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>C:\Users\Administrator\source\repos\QQDecryption\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>QQDecryption.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="UnlockQQ.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="UnlockQQ.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View File

@@ -37,7 +37,7 @@ import java.util.Map;
*/ */
public class AxisInnovatorsBox { public class AxisInnovatorsBox {
private static final Logger logger = LogManager.getLogger(AxisInnovatorsBox.class); private static final Logger logger = LogManager.getLogger(AxisInnovatorsBox.class);
private static final String VERSIONS = "0.0.2"; private static final String VERSIONS = "0.1.2";
private static final String[] AUTHOR = new String[]{ private static final String[] AUTHOR = new String[]{
"tzdwindows 7" "tzdwindows 7"
}; };
@@ -71,7 +71,6 @@ public class AxisInnovatorsBox {
LibraryLoad.loadLibrary("ThrowSafely"); LibraryLoad.loadLibrary("ThrowSafely");
} catch (Exception e) { } catch (Exception e) {
logger.error("Failed to load the 'FridaNative' library", e); logger.error("Failed to load the 'FridaNative' library", e);
throw new RuntimeException(e);
} }
} }
@@ -421,7 +420,6 @@ public class AxisInnovatorsBox {
logger.error("In unexpected errors", e); logger.error("In unexpected errors", e);
main.ex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); main.ex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.organizingCrashReports(e); main.organizingCrashReports(e);
throw new RuntimeException(e);
} }
} }

View File

@@ -1,6 +1,7 @@
package com.axis.innovators.box; package com.axis.innovators.box;
import com.axis.innovators.box.browser.MainApplication; import com.axis.innovators.box.browser.MainApplication;
import com.axis.innovators.box.browser.WindowRegistry;
import com.axis.innovators.box.decompilation.gui.ModernJarViewer; import com.axis.innovators.box.decompilation.gui.ModernJarViewer;
import com.axis.innovators.box.tools.ArgsParser; import com.axis.innovators.box.tools.ArgsParser;
import com.axis.innovators.box.tools.FolderCleaner; import com.axis.innovators.box.tools.FolderCleaner;

View File

@@ -57,6 +57,9 @@ public class CefAppManager {
try { try {
settings.windowless_rendering_enabled = false; settings.windowless_rendering_enabled = false;
settings.javascript_flags = "--expose-gc"; settings.javascript_flags = "--expose-gc";
settings.cache_path = FolderCreator.getLibraryFolder() + "/jcef/cache";
settings.root_cache_path = FolderCreator.getLibraryFolder() + "/jcef/cache";
settings.persist_session_cookies = true;
settings.log_severity = CefSettings.LogSeverity.LOGSEVERITY_VERBOSE; settings.log_severity = CefSettings.LogSeverity.LOGSEVERITY_VERBOSE;
String subprocessPath = FolderCreator.getLibraryFolder() + "/jcef/lib/win64/jcef_helper.exe"; String subprocessPath = FolderCreator.getLibraryFolder() + "/jcef/lib/win64/jcef_helper.exe";

View File

@@ -1,5 +1,6 @@
package com.axis.innovators.box.browser; package com.axis.innovators.box.browser;
import com.axis.innovators.box.browser.util.CodeExecutor;
import com.axis.innovators.box.tools.FolderCreator; import com.axis.innovators.box.tools.FolderCreator;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
@@ -8,6 +9,11 @@ import org.cef.browser.CefFrame;
import org.cef.browser.CefMessageRouter; import org.cef.browser.CefMessageRouter;
import org.cef.callback.CefQueryCallback; import org.cef.callback.CefQueryCallback;
import org.cef.handler.CefMessageRouterHandlerAdapter; import org.cef.handler.CefMessageRouterHandlerAdapter;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.PolyglotException;
import org.graalvm.polyglot.Value;
import org.json.JSONObject;
import org.python.util.PythonInterpreter;
import org.tzd.lm.LM; import org.tzd.lm.LM;
import javax.swing.*; import javax.swing.*;
@@ -28,13 +34,14 @@ import java.util.concurrent.atomic.AtomicReference;
* 这是一个简单的示例程序用于展示如何使用JCEF来创建一个简单的浏览器窗口。 * 这是一个简单的示例程序用于展示如何使用JCEF来创建一个简单的浏览器窗口。
* @author tzdwindows 7 * @author tzdwindows 7
*/ */
public class MainApplication { public class MainApplication {
private static final ExecutorService executor = Executors.newCachedThreadPool(); private static final ExecutorService executor = Executors.newCachedThreadPool();
private static long modelHandle; private static long modelHandle;
private static long ctxHandle; private static long ctxHandle;
private static boolean isSystem = true; private static boolean isSystem = true;
public static void main(String[] args) { public static void main(String[] args) {
//popupHTMLWindow();
} }
@@ -79,6 +86,118 @@ public class MainApplication {
}); });
} }
public static void popupCCodeEditorWindow() {
AtomicReference<BrowserWindow> window = new AtomicReference<>();
SwingUtilities.invokeLater(() -> {
WindowRegistry.getInstance().createNewWindow("main", builder ->
window.set(builder.title("TzdC 代码编辑器")
.icon(new ImageIcon(Objects.requireNonNull(MainApplication.class.getClassLoader().getResource("icons/logo.png"))).getImage())
.size(1487, 836)
.htmlPath(FolderCreator.getJavaScriptFolder() + "\\" + "CCodeEditor.html")
.operationHandler(createOperationHandler())
.build())
);
CefMessageRouter msgRouter = window.get().getMsgRouter();
if (msgRouter != null) {
msgRouter.addHandler(new CefMessageRouterHandlerAdapter() {
@Override
public boolean onQuery(CefBrowser browser, CefFrame frame, long queryId,
String request, boolean persistent, CefQueryCallback callback) {
try {
JSONObject requestJson = new JSONObject(request);
if ("executeCode".equals(requestJson.optString("type"))) {
String code = requestJson.optString("code");
String language = requestJson.optString("language");
// 调用代码执行逻辑
String result = CodeExecutor.executeCode(code, language,null);
JSONObject response = new JSONObject();
response.put("status", "success");
response.put("output", result);
callback.success(response.toString());
return true;
}
} catch (Exception e) {
JSONObject error = new JSONObject();
error.put("status", "error");
error.put("message", e.getMessage());
callback.failure(500, error.toString());
}
return false;
}
@Override
public void onQueryCanceled(CefBrowser browser, CefFrame frame, long queryId) {
// 处理请求取消
}
}, true);
}
});
}
public static void popupCodeEditorWindow() {
AtomicReference<BrowserWindow> window = new AtomicReference<>();
SwingUtilities.invokeLater(() -> {
WindowRegistry.getInstance().createNewWindow("main", builder ->
window.set(builder.title("代码编辑器")
.icon(new ImageIcon(Objects.requireNonNull(MainApplication.class.getClassLoader().getResource("icons/logo.png"))).getImage())
.size(1487, 836)
.htmlPath(FolderCreator.getJavaScriptFolder() + "\\" + "CodeEditor.html")
.operationHandler(createOperationHandler())
.build())
);
CefMessageRouter msgRouter = window.get().getMsgRouter();
if (msgRouter != null) {
msgRouter.addHandler(new CefMessageRouterHandlerAdapter() {
@Override
public boolean onQuery(CefBrowser browser, CefFrame frame, long queryId,
String request, boolean persistent, CefQueryCallback callback) {
try {
JSONObject requestJson = new JSONObject(request);
if ("executeCode".equals(requestJson.optString("type"))) {
String code = requestJson.optString("code");
String language = requestJson.optString("language");
// 调用代码执行逻辑
String result = executeCode(code, language);
JSONObject response = new JSONObject();
response.put("status", "success");
response.put("output", result);
callback.success(response.toString());
return true;
}
} catch (Exception e) {
JSONObject error = new JSONObject();
error.put("status", "error");
error.put("message", e.getMessage());
callback.failure(500, error.toString());
}
return false;
}
@Override
public void onQueryCanceled(CefBrowser browser, CefFrame frame, long queryId) {
// 处理请求取消
}
}, true);
}
});
}
public static String executeCode(String code, String language) {
return CodeExecutor.executeCode(code, language,new CodeExecutor.OutputListener() {
@Override
public void onOutput(String newOutput) {}
});
}
private static Value executeC(Context context, String code) {
return context.eval("c", code);
}
/** /**
* 弹出html预览窗口 * 弹出html预览窗口
*/ */
@@ -107,11 +226,11 @@ public class MainApplication {
Path filePath = Paths.get(path); Path filePath = Paths.get(path);
//// 验证文件存在性 // 验证文件存在性
//if (!Files.exists(filePath)) { if (!Files.exists(filePath)) {
// callback.failure(404, "{\"code\":404,\"message\":\"文件未找到\"}"); callback.failure(404, "{\"code\":404,\"message\":\"文件未找到\"}");
// return true; return true;
//} }
// 读取文件内容 // 读取文件内容
String content = Files.readString(filePath, StandardCharsets.UTF_8); String content = Files.readString(filePath, StandardCharsets.UTF_8);

View File

@@ -1,5 +1,14 @@
package com.axis.innovators.box.browser; package com.axis.innovators.box.browser;
import com.axis.innovators.box.tools.FolderCreator;
import org.cef.CefApp;
import org.cef.browser.CefBrowser;
import org.cef.browser.CefFrame;
import org.cef.handler.CefLoadHandlerAdapter;
import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import java.util.Map; import java.util.Map;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -58,6 +67,8 @@ public class WindowRegistry {
config.accept(builder); config.accept(builder);
BrowserWindow window = builder.build(); BrowserWindow window = builder.build();
registerWindow(window); registerWindow(window);
loadExtLibsPath(window);
} }
/** /**
@@ -70,5 +81,59 @@ public class WindowRegistry {
config.accept(builder); config.accept(builder);
BrowserWindowJDialog window = builder.build(); BrowserWindowJDialog window = builder.build();
registerChildWindow(window); registerChildWindow(window);
loadExtLibsPath(window);
}
private void loadExtLibsPath(BrowserWindow window) {
CefBrowser cefBrowser = window.getBrowser();
if (cefBrowser != null)
// 使用 CefClient 的调度方法(如果可用)或直接添加 LoadHandler
cefBrowser.getClient().addLoadHandler(new CefLoadHandlerAdapter() {
@Override
public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) {
if (frame.isMain()) {
try {
String extLibsPath = FolderCreator.getJavaScriptFolder() + "\\" + "extLibs";
File extLibsDir = new File(extLibsPath);
if (!extLibsDir.exists() || !extLibsDir.isDirectory()) {
throw new IOException("extLibs目录无效: " + extLibsPath);
}
String script = "window.extLibsPath = " + JSONObject.valueToString(extLibsPath) + ";";
browser.executeJavaScript(script, frame.getURL(), 0);
} catch (Exception e) {
System.err.println("注入extLibsPath失败: " + e.getMessage());
e.printStackTrace();
}
}
}
});
}
private void loadExtLibsPath(BrowserWindowJDialog window) {
CefBrowser cefBrowser = window.getBrowser();
if (cefBrowser != null)
// 使用 CefClient 的调度方法(如果可用)或直接添加 LoadHandler
cefBrowser.getClient().addLoadHandler(new CefLoadHandlerAdapter() {
@Override
public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) {
if (frame.isMain()) {
try {
String extLibsPath = FolderCreator.getJavaScriptFolder() + "\\" + "extLibs";
File extLibsDir = new File(extLibsPath);
if (!extLibsDir.exists() || !extLibsDir.isDirectory()) {
throw new IOException("extLibs目录无效: " + extLibsPath);
}
String script = "window.extLibsPath = " + JSONObject.valueToString(extLibsPath) + ";";
browser.executeJavaScript(script, frame.getURL(), 0);
} catch (Exception e) {
System.err.println("注入extLibsPath失败: " + e.getMessage());
e.printStackTrace();
}
}
}
});
} }
} }

View File

@@ -0,0 +1,392 @@
package com.axis.innovators.box.browser.util;
import com.axis.innovators.box.tools.LibraryLoad;
import org.jnc.DllExtractor;
import org.jnc.windows.JncNative;
import org.python.util.PythonInterpreter;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
public class CodeExecutor {
// 用于捕获输出的回调接口
public interface OutputListener {
void onOutput(String newOutput);
}
public static String executeCode(String code, String language, OutputListener listener) {
switch (language.toLowerCase()) {
case "python":
return executePythonNative(code, listener);
case "c":
case "cpp":
return executeC(code, listener);
case "java":
return executeJavaCode(code, listener);
default:
return "不支持的语言类型: " + language;
}
}
public static String executeJavaCode(String code, OutputListener listener) {
Path tempDir = null;
try {
// ===== 1. 创建临时目录 =====
tempDir = Files.createTempDirectory("javaCode");
// ===== 2. 写入Java源文件强制UTF-8=====
Path javaFile = tempDir.resolve("Main.java");
Files.writeString(javaFile,
code,
StandardCharsets.UTF_8
);
// ===== 3. 编译时指定编码 =====
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, StandardCharsets.UTF_8);
List<String> options = new ArrayList<>();
options.add("-encoding");
options.add("UTF-8");
options.add("-d");
options.add(tempDir.toString());
JavaCompiler.CompilationTask task = compiler.getTask(
null,
fileManager,
null,
options,
null,
fileManager.getJavaFileObjects(javaFile)
);
if (!task.call()) {
return "编译失败";
}
// ===== 4. 执行配置 =====
String javaExe = Path.of(System.getProperty("java.home"), "bin", "java").toString();
ProcessBuilder pb = new ProcessBuilder(
javaExe,
"-Dfile.encoding=UTF-8",
"-Dsun.stdout.encoding=UTF-8", // 针对OpenJDK的特殊设置
"-Dsun.stderr.encoding=UTF-8",
"-cp",
tempDir.toString(),
"Main"
);
// ===== 5. 设置环境变量 =====
Map<String, String> env = pb.environment();
env.put("JAVA_TOOL_OPTIONS", "-Dfile.encoding=UTF-8");
env.put("LANG", "en_US.UTF-8"); // Linux/macOS
env.put("LC_ALL", "en_US.UTF-8");
// ===== 6. 输出处理 =====
pb.redirectErrorStream(true);
Process process = pb.start();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
StringBuilder output = new StringBuilder();
char[] buffer = new char[4096];
int charsRead;
while ((charsRead = reader.read(buffer)) != -1) {
String chunk = new String(buffer, 0, charsRead);
output.append(chunk);
if (listener != null) {
// 处理控制台编码转换Windows专用
if (System.getProperty("os.name").startsWith("Windows")) {
chunk = new String(chunk.getBytes(StandardCharsets.UTF_8), "GBK");
}
listener.onOutput(chunk);
}
}
int exitCode = process.waitFor();
return output.toString() + "\n退出码: " + exitCode;
}
} catch (Exception e) {
return "执行错误: " + e.getMessage();
} finally {
// 清理代码...
}
}
/**
* 需要用户安装python环境
*/
private static String executePythonNative(String code, OutputListener listener) {
try {
Path pythonFile = Files.createTempFile("script_", ".py");
Files.writeString(pythonFile,
"# -*- coding: utf-8 -*-\n" + code,
StandardCharsets.UTF_8
);
ProcessBuilder pb = new ProcessBuilder("python", pythonFile.toString())
.redirectErrorStream(true);
Map<String, String> env = pb.environment();
env.put("PYTHONIOENCODING", "UTF-8");
env.put("PYTHONUTF8", "1");
Process process = pb.start();
StringBuilder output = new StringBuilder();
Thread outputThread = new Thread(() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
String finalLine = line + "\n";
output.append(finalLine);
if (listener != null) {
listener.onOutput(finalLine);
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
outputThread.start();
// 等待执行完成
int exitCode = process.waitFor();
outputThread.join();
// 清理文件
Files.deleteIfExists(pythonFile);
return String.format("退出码: %d\n输出内容:\n%s", exitCode, output);
} catch (Exception e) {
return "执行错误: " + e.getMessage();
}
}
private static String executeC(String code, OutputListener listener) {
Path tempDir = null;
Path cFile = null;
Path exeFile = null;
try {
// 创建临时工作目录
tempDir = Files.createTempDirectory("c_compile_");
// 生成C源代码文件
cFile = tempDir.resolve("program.c");
Files.writeString(cFile, code, StandardCharsets.UTF_8);
// 生成可执行文件路径
exeFile = tempDir.resolve("program.exe");
// 1. 编译代码 -------------------------------------------------
String tccPath =System.getProperty("user.dir") + "/library/tcc/tcc.exe";
Process compileProcess;
if (listener != null) {
compileProcess = new ProcessBuilder(
tccPath,
"-o", exeFile.toString(),
cFile.toString()
)
.directory(tempDir.toFile())
.redirectErrorStream(true)
.start();
// 捕获编译输出
StringBuilder compileOutput = new StringBuilder();
Thread compileOutputThread = new Thread(() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(compileProcess.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
compileOutput.append(line).append("\n");
if (listener != null) {
listener.onOutput("[编译输出] " + line + "\n");
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
compileOutputThread.start();
// 等待编译完成
int compileExitCode = compileProcess.waitFor();
compileOutputThread.join(1000);
if (compileExitCode != 0) {
return "编译失败:\n" + compileOutput;
}
// 2. 执行程序 -------------------------------------------------
Process executeProcess = new ProcessBuilder(exeFile.toString())
.directory(tempDir.toFile())
.redirectErrorStream(true)
.start();
// 实时输出处理
AtomicReference<StringBuilder> execOutput = new AtomicReference<>(new StringBuilder());
Thread executeOutputThread = new Thread(() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(executeProcess.getInputStream(), StandardCharsets.UTF_8))) {
char[] buffer = new char[1024];
int charsRead;
while ((charsRead = reader.read(buffer)) != -1) {
String outputChunk = new String(buffer, 0, charsRead);
execOutput.get().append(outputChunk);
if (listener != null) {
listener.onOutput(outputChunk);
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
executeOutputThread.start();
// 等待执行完成最多10秒
boolean finished = executeProcess.waitFor(10, TimeUnit.SECONDS);
executeOutputThread.join(1000);
if (!finished) {
executeProcess.destroyForcibly();
return "执行超时\n部分输出:\n" + execOutput.get();
}
// 获取最终输出
String finalOutput = execOutput.get().toString();
int exitCode = executeProcess.exitValue();
return String.format("执行结果: %s\n退出码: %d\n输出内容:\n%s",
exitCode == 0 ? "成功" : "失败",
exitCode,
finalOutput);
} else {
new ProcessBuilder(
tccPath,
"-o", exeFile.toString(),
cFile.toString()
)
.directory(tempDir.toFile())
.redirectErrorStream(true)
.start();
new ProcessBuilder(
"cmd.exe",
"/c",
"start",
"\"Tzd输出窗口\"",
"cmd.exe",
"/K",
"chcp 65001 & ",
exeFile.toString()
).start();
return String.format("执行结果: %s\n退出码: %d\n输出内容:\n%s",
"成功",
0,
"");
}
} catch (Exception e) {
return "执行错误: " + e.getMessage();
} finally {
// 清理临时文件
try {
if (listener != null){
if (cFile != null) Files.deleteIfExists(cFile);
if (exeFile != null) Files.deleteIfExists(exeFile);
if (tempDir != null) Files.deleteIfExists(tempDir);
}
} catch (IOException e) {
System.err.println("临时文件清理失败: " + e.getMessage());
}
}
}
private static String captureProcessOutput(Process process, OutputListener listener)
throws IOException {
StringBuilder totalOutput = new StringBuilder();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
totalOutput.append(line).append("\n");
if (listener != null) {
listener.onOutput(line + "\n");
}
}
}
return totalOutput.toString();
}
// 输出监控线程
private static class OutputMonitor implements Runnable {
private final BufferedReader reader;
private final OutputListener listener;
private volatile boolean running = true;
private final StringBuilder totalOutput = new StringBuilder();
public OutputMonitor(BufferedReader reader, OutputListener listener) {
this.reader = reader;
this.listener = listener;
}
public void run() {
try {
while (running) {
if (reader.ready()) {
String line = reader.readLine();
if (line != null) {
totalOutput.append(line).append("\n");
if (listener != null) {
listener.onOutput(line + "\n");
}
}
} else {
Thread.sleep(50);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void stop() {
running = false;
}
public String getTotalOutput() {
return totalOutput.toString();
}
}
// 使用方法
public static void main(String[] args) {
String pythonCode = "#include <stdio.h>\n" +
"\n" +
"int main() {\n" +
" while (1){\n" +
" printf(\"Hello World\\n\");\n" +
"}\n" +
" return 0;\n" +
"}";
executeCode(pythonCode, "c", null);
}
}

View File

@@ -48,6 +48,7 @@ public class RegistrationTool {
} }
})); }));
MainWindow.ToolCategory programmingToolsCategory = new MainWindow.ToolCategory("编程工具", MainWindow.ToolCategory programmingToolsCategory = new MainWindow.ToolCategory("编程工具",
"programming/programming.png", "programming/programming.png",
"编程工具"); "编程工具");
@@ -62,6 +63,26 @@ public class RegistrationTool {
} }
})); }));
programmingToolsCategory.addTool(new MainWindow.ToolItem("C语言编辑器", "programming/LanguageEditor/file-editing.png",
"C语言编译器智能化的idea" +
"\n作者tzdwindows 7", ++id, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
// Window owner = SwingUtilities.windowForComponent((Component) e.getSource());
MainApplication.popupCCodeEditorWindow();
}
}));
programmingToolsCategory.addTool(new MainWindow.ToolItem("多语言在线执行(当遇到无限循环时会抛出错误)", "programming/LanguageEditor/file-editing.png",
"多语言在线执行,当遇到无限循环时会抛出错误" +
"\n作者tzdwindows 7", ++id, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
// Window owner = SwingUtilities.windowForComponent((Component) e.getSource());
MainApplication.popupCodeEditorWindow();
}
}));
MainWindow.ToolCategory aICategory = new MainWindow.ToolCategory("AI工具", MainWindow.ToolCategory aICategory = new MainWindow.ToolCategory("AI工具",
"ai/ai.png", "ai/ai.png",
"人工智能/大语言模型"); "人工智能/大语言模型");

View File

@@ -0,0 +1,96 @@
package org.QQdecryption;
import com.axis.innovators.box.tools.FolderCreator;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
public class QQMusicAutoDecryptor {
/**
* 解密QQ加密的文件
* @param inputPath 源文件路径
* @param outputDir 标准输出目录路径
*/
public static void decrypt(String inputPath, String outputDir) {
try {
// 构建UnlockQQ.exe路径
String unlockExe = FolderCreator.getLibraryFolder() + File.separator + "UnlockQQ.exe";
// 处理输出文件名和路径
File inputFile = new File(inputPath);
String originalName = inputFile.getName();
// 创建扩展名映射表(可根据需要扩展)
Map<String, String> formatMap = new HashMap<>() {{
put(".mflac", ".flac");
put(".mgg", ".ogg");
put(".qmc0", ".mp3");
put(".qmc3", ".mp3");
put(".qmcflac", ".flac");
put(".qmcogg", ".ogg");
put(".tkm", ".mp3");
put(".qmc2", ".mp3");
put(".bkcmp3", ".mp3");
put(".bkcflac", ".flac");
put(".ogg", ".ogg");
}};
// 自动识别并转换文件格式
String outputFileName = originalName;
int lastDotIndex = originalName.lastIndexOf('.');
if (lastDotIndex > 0) {
String ext = originalName.substring(lastDotIndex).toLowerCase();
if (formatMap.containsKey(ext)) {
outputFileName = originalName.substring(0, lastDotIndex)
+ formatMap.get(ext);
} else {
throw new RuntimeException("未知文件格式: " + ext);
}
}
File outputFile = new File(outputDir, outputFileName);
// 构建命令参数(处理带空格的路径)
String[] cmd = {
unlockExe,
"\"" + inputFile.getAbsolutePath() + "\"",
"\"" + outputFile.getAbsolutePath() + "\""
};
// 执行解密命令
Process process = Runtime.getRuntime().exec(cmd);
int exitCode = process.waitFor();
// 检查执行结果
if (exitCode == 0) {
System.out.println("解密成功: " + outputFile.getAbsolutePath());
} else {
System.err.println("解密失败,错误码: " + exitCode);
printProcessError(process);
}
} catch (IOException | InterruptedException e) {
System.err.println("解密过程中出现异常: ");
e.printStackTrace();
throw new RuntimeException("解密过程中出现异常: ", e);
}
}
// 添加错误流打印方法
private static void printProcessError(Process process) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getErrorStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.err.println("[EXE ERROR] " + line);
throw new RuntimeException("解密失败: " + line);
}
}
}
}

View File

@@ -0,0 +1,167 @@
package org.QQdecryption.ui;
import org.QQdecryption.QQMusicAutoDecryptor;
import com.formdev.flatlaf.FlatIntelliJLaf;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.io.File;
import java.util.List;
public class DecryptionUI extends JFrame {
private JProgressBar progressBar;
private JTextArea logArea;
public DecryptionUI() {
initUI();
setupDnD();
}
private void initUI() {
setTitle("QQ音乐文件解锁工具 v2.1");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(800, 600);
setLocationRelativeTo(null);
setupModernLookAndFeel();
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
mainPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
// 拖放区域
JPanel dropZone = createDropZone();
mainPanel.add(dropZone, BorderLayout.CENTER);
// 控制面板
JPanel controlPanel = createControlPanel();
mainPanel.add(controlPanel, BorderLayout.SOUTH);
// 日志区域
logArea = new JTextArea();
logArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(logArea);
scrollPane.setPreferredSize(new Dimension(0, 150));
mainPanel.add(scrollPane, BorderLayout.SOUTH);
add(mainPanel);
}
private void setupModernLookAndFeel() {
try {
UIManager.setLookAndFeel(new FlatIntelliJLaf());
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
}
private JPanel createDropZone() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createDashedBorder(null, 3, 5));
panel.setBackground(UIManager.getColor("Panel.background").darker());
JLabel dropLabel = new JLabel("拖放QQ音乐文件到此区域", SwingConstants.CENTER);
dropLabel.setFont(new Font("微软雅黑", Font.BOLD, 18));
dropLabel.setForeground(new Color(0x666666));
panel.add(dropLabel);
return panel;
}
private JPanel createControlPanel() {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 10));
// 进度条
progressBar = new JProgressBar();
progressBar.setPreferredSize(new Dimension(200, 20));
progressBar.setStringPainted(true);
panel.add(progressBar);
return panel;
}
private void setupDnD() {
new DropTarget(this, new DropTargetAdapter() {
@Override
public void drop(DropTargetDropEvent dtde) {
try {
dtde.acceptDrop(DnDConstants.ACTION_COPY);
List<File> files = (List<File>) dtde.getTransferable()
.getTransferData(DataFlavor.javaFileListFlavor);
processFiles(files);
} catch (Exception ex) {
logError("文件拖放错误: " + ex.getMessage());
}
}
});
}
private void processFiles(List<File> files) {
SwingWorker<Void, Void> worker = new SwingWorker<>() {
@Override
protected Void doInBackground() {
progressBar.setIndeterminate(true);
for (File file : files) {
decryptFile(file);
}
return null;
}
@Override
protected void done() {
progressBar.setIndeterminate(false);
JOptionPane.showMessageDialog(DecryptionUI.this,
"处理完成!",
"完成",
JOptionPane.INFORMATION_MESSAGE);
}
};
worker.execute();
}
private void decryptFile(File inputFile) {
try {
logMessage("开始处理: " + inputFile.getName());
// 自动获取源文件所在目录
File outputDir = inputFile.getParentFile();
QQMusicAutoDecryptor.decrypt(
inputFile.getAbsolutePath(),
outputDir.getAbsolutePath()
);
logMessage("✓ 成功解密保存到: " + outputDir.getAbsolutePath());
} catch (Exception ex) {
logError("解密失败: " + ex.getMessage());
}
}
private void logMessage(String message) {
SwingUtilities.invokeLater(() -> {
logArea.append("[INFO] " + message + "\n");
logArea.setCaretPosition(logArea.getDocument().getLength());
});
}
private void logError(String error) {
SwingUtilities.invokeLater(() -> {
logArea.append("[ERROR] " + error + "\n");
logArea.setCaretPosition(logArea.getDocument().getLength());
});
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
try {
UIManager.setLookAndFeel(new FlatIntelliJLaf());
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
new DecryptionUI().setVisible(true);
});
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB