@atlaskit/editor-plugin-code-block
Version:
Code block plugin for @atlaskit/editor-core
194 lines (181 loc) • 8.72 kB
JavaScript
import _typeof from "@babel/runtime/helpers/typeof";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
/* eslint-disable require-unicode-regexp */
// Conservative weighted-regex heuristic for common high-confidence snippets, not a full classifier.
// Ambiguous snippets intentionally return null so users can select the language manually.
var MAX_DETECTION_CHARS = 10000;
var MIN_DETECTION_SCORE = 3; // Require at least one medium-confidence signal before auto-selecting.
var MIN_SCORE_GAP = 2; // Avoid auto-selecting when top two languages are too close to distinguish.
// looksLikeJson regexes
var JSON_START_REGEX = /^[{[]/;
var JSON_END_REGEX = /[}\]]$/;
// html regexes
var HTML_DOCTYPE_REGEX = //gi;
var match;
while ((match = tagPattern.exec(code)) !== null) {
var _match = match,
_match2 = _slicedToArray(_match, 2),
tag = _match2[0],
tagName = _match2[1];
if (tag.endsWith('/>')) {
continue;
}
if (tag.startsWith('</')) {
if (openTags.has(tagName.toLowerCase())) {
return true;
}
} else {
openTags.add(tagName.toLowerCase());
}
}
return false;
};
var looksLikeJson = function looksLikeJson(code) {
var trimmed = code.trim();
if (!JSON_START_REGEX.test(trimmed) || !JSON_END_REGEX.test(trimmed)) {
return false;
}
try {
var parsed = JSON.parse(trimmed);
return parsed !== null && _typeof(parsed) === 'object';
} catch (_unused) {
return false;
}
};
var getLanguageScores = function getLanguageScores(code) {
return [{
language: 'json',
score: looksLikeJson(code) ? 8 : 0
}, {
language: 'html',
score: scorePatterns(code, [[HTML_DOCTYPE_REGEX, 5], [HTML_TAG_REGEX, 2]]) + (looksLikeHtmlTagPair(code) ? 3 : 0)
}, {
language: 'css',
score: scorePatterns(code, [[CSS_AT_RULE_REGEX, 3], [CSS_SELECTOR_PROPERTY_REGEX, 5], [CSS_PROPERTY_REGEX, 3]])
}, {
language: 'sql',
score: scorePatterns(code, [[SQL_SELECT_FROM_REGEX, 5], [SQL_DML_REGEX, 5], [SQL_CLAUSE_REGEX, 2]])
}, {
language: 'typescript',
score: scorePatterns(code, [[TS_INTERFACE_TYPE_REGEX, 5], [TS_IMPORT_EXPORT_TYPE_REGEX, 4], [TS_TYPED_VAR_REGEX, 4], [TS_RETURN_TYPE_REGEX, 3], [TS_ADVANCED_REGEX, 3], [TS_ACCESS_MODIFIER_REGEX, 5], [TS_TYPED_ARROW_PARAM_REGEX, 5]])
}, {
language: 'javascript',
score: scorePatterns(code, [[JS_VAR_REGEX, 3], [JS_FUNCTION_REGEX, 3], [JS_ARROW_REGEX, 3], [JS_IMPORT_EXPORT_REGEX, 3], [JS_COMMON_API_REGEX, 3]])
}, {
language: 'python',
score: scorePatterns(code, [[PY_DEF_REGEX, 5], [PY_CLASS_REGEX, 4], [PY_IMPORT_REGEX, 3], [PY_CONTROL_REGEX, 2], [PY_PRINT_REGEX, 2]])
}, {
language: 'java',
score: scorePatterns(code, [[JAVA_CLASS_REGEX, 5], [JAVA_MAIN_REGEX, 5], [JAVA_PRINTLN_REGEX, 4], [JAVA_MEMBER_REGEX, 3]])
}, {
language: 'go',
score: scorePatterns(code, [[GO_PACKAGE_REGEX, 5], [GO_FUNC_REGEX, 5], [GO_PRINTLN_REGEX, 3], [GO_IMPORT_REGEX, 2]])
}, {
language: 'ruby',
score: scorePatterns(code, [[RUBY_DEF_REGEX, 4], [RUBY_CLASS_REGEX, 3], [RUBY_END_REGEX, 3], [RUBY_COMMON_API_REGEX, 3], [RUBY_BLOCK_REGEX, 2]])
}, {
language: 'rust',
score: scorePatterns(code, [[RUST_FN_REGEX, 5], [RUST_LET_MUT_REGEX, 3], [RUST_PRINTLN_REGEX, 4], [RUST_USE_REGEX, 3], [RUST_STRUCT_REGEX, 3]])
}, {
language: 'shell',
score: scorePatterns(code, [[SHELL_SHEBANG_REGEX, 6], [SHELL_CONTROL_REGEX, 4], [SHELL_FI_DONE_REGEX, 3], [SHELL_COMMAND_REGEX, 3], [SHELL_VAR_REGEX, 2]])
}];
};
export var detectLanguage = function detectLanguage(code) {
var trimmedCode = code.trim();
if (trimmedCode.length < 8) {
return null;
}
var codeForDetection = trimmedCode.slice(0, MAX_DETECTION_CHARS);
var _getLanguageScores$fi = getLanguageScores(codeForDetection).filter(function (_ref3) {
var score = _ref3.score;
return score > 0;
}).sort(function (a, b) {
return b.score - a.score;
}),
_getLanguageScores$fi2 = _slicedToArray(_getLanguageScores$fi, 2),
best = _getLanguageScores$fi2[0],
secondBest = _getLanguageScores$fi2[1];
if (!best || best.score < MIN_DETECTION_SCORE) {
return null;
}
if (secondBest && best.score - secondBest.score < MIN_SCORE_GAP) {
return null;
}
return best.language;
};