diff --git a/tools/chatgui/src/code_language.cpp b/tools/chatgui/src/code_language.cpp index ef516d2e1..4a7a2eeeb 100644 --- a/tools/chatgui/src/code_language.cpp +++ b/tools/chatgui/src/code_language.cpp @@ -42,7 +42,8 @@ const Rule rules[] = { {Php, 4, QRegularExpression(R"(\$[a-zA-Z_]\w*\s*(?:->|\[|=))")}, {Php, 4, QRegularExpression(R"(\bfunction\s+\w+\s*\([^\n)]*\$|\b(?:public|private|protected)\s+(?:static\s+)?function\b)")}, {Php, 3, QRegularExpression(R"(\b(?:echo|require_once|include_once)\b|\barray\s*\(|\$this\b)")}, - {JavaScript, 4, QRegularExpression(R"(\b(?:const|let|var)\s+[a-zA-Z_$][\w$]*\s*=)")}, + {JavaScript, 4, QRegularExpression(R"(\b(?:const|var)\s+[a-zA-Z_$][\w$]*\s*=)")}, + {JavaScript, 2, QRegularExpression(R"(\blet\s+[a-zA-Z_$][\w$]*\s*=)")}, {JavaScript, 3, QRegularExpression(R"(=>|\bfunction\s*[\w$]*\s*\()")}, {JavaScript, 4, QRegularExpression(R"(\b(?:module\.exports|exports\.\w+|console\.\w+|document\.\w+)\b)")}, {JavaScript, 4, QRegularExpression(R"(^\s*(?:export\s+(?:default|function|const|class)\b|import\s+[^;\n]+\s+from\b))", @@ -74,10 +75,15 @@ QString detectCodeLanguage(QStringView source) { } std::array scores{}; for (const auto& rule : rules) if (rule.pattern.match(code).hasMatch()) scores[rule.language] += rule.weight; - // Фрагменты HTML без doctype: нужен парный известный тег; JSX с объявлениями JS не выбираем как HTML. + // Структурные теги отличают HTML с вложенным JS/CSS; одиночный div внутри JSX недостаточен. + static const QRegularExpression structuralTags(R"(]*>)", + QRegularExpression::CaseInsensitiveOption); static const QRegularExpression tags(R"(<(div|span|p|a|ul|li|table|section|form|button|h[1-6])\b[^<>]*>[\s\S]*?)", QRegularExpression::CaseInsensitiveOption); - if (scores[JavaScript] == 0 && tags.match(code).hasMatch()) { scores[Html] = 7; scores[Css] = 0; } + if (structuralTags.match(code).hasMatch() || (scores[JavaScript] == 0 && tags.match(code).hasMatch())) { + GUI_DEBUG("code language: result=HTML markup tags sampled=%d", int(sample.size())); + return QStringLiteral("HTML"); + } // std:: и Type::method встречаются также в Rust; use/fn/impl отличают его от C++. if (scores[Rust] >= 7) scores[Cpp] = 0; // C является подмножеством C++: специфичные конструкции C++ имеют приоритет. diff --git a/tools/chatgui/tests/test_code_language.cpp b/tools/chatgui/tests/test_code_language.cpp index df8601ad5..93d1d67da 100644 --- a/tools/chatgui/tests/test_code_language.cpp +++ b/tools/chatgui/tests/test_code_language.cpp @@ -29,6 +29,9 @@ private slots: QTest::newRow("html") << "\n" << "HTML"; QTest::newRow("html-fragment") << "
Hello
" << "HTML"; QTest::newRow("html-css") << "

Hello

" << "HTML"; + QTest::newRow("html-js") << "" << "HTML"; + QTest::newRow("html-script-list") << "" << "HTML"; + QTest::newRow("ambiguous-let-arrow") << "let x = match value { Value::A => true, Value::B => false };" << ""; QTest::newRow("empty") << "" << ""; QTest::newRow("ambiguous") << "int x = 42;" << ""; QTest::newRow("prose") << "Java and Kotlin have class and function declarations; use CSS for color." << "";