@atlaskit/editor-plugin-code-block 14.1.5 → 14.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @atlaskit/editor-plugin-code-block
2
2
 
3
+ ## 14.1.7
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+
9
+ ## 14.1.6
10
+
11
+ ### Patch Changes
12
+
13
+ - [`73743eb8b36e6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/73743eb8b36e6) -
14
+ CLeanup prefer static regex violations
15
+ - Updated dependencies
16
+
3
17
  ## 14.1.5
4
18
 
5
19
  ### Patch Changes
@@ -9,18 +9,22 @@ var BRACKET_MAP = exports.BRACKET_MAP = {
9
9
  '[': ']',
10
10
  '(': ')'
11
11
  };
12
+ // when directly before a closing bracket
13
+ // Ignored via go/ees005
14
+ // eslint-disable-next-line require-unicode-regexp
15
+ var CLOSING_BRACKET_REGEX = /^[}\])]/;
16
+ // exclusion: when directly before a non-whitespace character
17
+ // Ignored via go/ees005
18
+ // eslint-disable-next-line require-unicode-regexp
19
+ var NON_WHITESPACE_AFTER_REGEX = /^[^\s]/;
12
20
  var shouldAutoCloseBracket = exports.shouldAutoCloseBracket = function shouldAutoCloseBracket(before, after) {
13
21
  // when directly before a closing bracket
14
- // Ignored via go/ees005
15
- // eslint-disable-next-line require-unicode-regexp
16
- if (/^[}\])]/.test(after)) {
22
+ if (CLOSING_BRACKET_REGEX.test(after)) {
17
23
  return true;
18
24
  }
19
25
 
20
26
  // exclusion: when directly before a non-whitespace character
21
- // Ignored via go/ees005
22
- // eslint-disable-next-line require-unicode-regexp
23
- if (/^[^\s]/.test(after)) {
27
+ if (NON_WHITESPACE_AFTER_REGEX.test(after)) {
24
28
  return false;
25
29
  }
26
30
  return true;
@@ -9,27 +9,34 @@ var QUOTE_MAP = exports.QUOTE_MAP = {
9
9
  '"': '"',
10
10
  '`': '`'
11
11
  };
12
+ // when directly before a closing bracket
13
+ // Ignored via go/ees005
14
+ // eslint-disable-next-line require-unicode-regexp
15
+ var CLOSING_BRACKET_REGEX = /^[}\])]/;
16
+ // exclusion: when directly before a non-whitespace character
17
+ // Ignored via go/ees005
18
+ // eslint-disable-next-line require-unicode-regexp
19
+ var NON_WHITESPACE_AFTER_REGEX = /^[^\s]/;
20
+ // exclusion: when directly after a letter or quote
21
+ // Ignored via go/ees005
22
+ // eslint-disable-next-line require-unicode-regexp
23
+ var ALPHANUMERIC_END_REGEX = /[A-Za-z0-9]$/;
24
+ // Ignored via go/ees005
25
+ // eslint-disable-next-line require-unicode-regexp
26
+ var QUOTE_END_REGEX = /[\'\"\'`]$/;
12
27
  var shouldAutoCloseQuote = exports.shouldAutoCloseQuote = function shouldAutoCloseQuote(before, after) {
13
28
  // when directly before a closing bracket
14
- // Ignored via go/ees005
15
- // eslint-disable-next-line require-unicode-regexp
16
- if (/^[}\])]/.test(after)) {
29
+ if (CLOSING_BRACKET_REGEX.test(after)) {
17
30
  return true;
18
31
  }
19
32
 
20
33
  // exclusion: when directly before a non-whitespace character
21
- // Ignored via go/ees005
22
- // eslint-disable-next-line require-unicode-regexp
23
- if (/^[^\s]/.test(after)) {
34
+ if (NON_WHITESPACE_AFTER_REGEX.test(after)) {
24
35
  return false;
25
36
  }
26
37
 
27
38
  // exclusion: when directly after a letter or quote
28
- // Ignored via go/ees005
29
- // eslint-disable-next-line require-unicode-regexp
30
- // Ignored via go/ees005
31
- // eslint-disable-next-line require-unicode-regexp
32
- if (/[A-Za-z0-9]$/.test(before) || /[\'\"\`]$/.test(before)) {
39
+ if (ALPHANUMERIC_END_REGEX.test(before) || QUOTE_END_REGEX.test(before)) {
33
40
  return false;
34
41
  }
35
42
  return true;
@@ -12,6 +12,8 @@ var _utils = require("@atlaskit/editor-common/utils");
12
12
  var _utils2 = require("@atlaskit/editor-prosemirror/utils");
13
13
  var _prosemirrorInputRules = require("@atlaskit/prosemirror-input-rules");
14
14
  var _transformToCodeBlock = require("./transform-to-code-block");
15
+ // eslint-disable-next-line require-unicode-regexp
16
+ var THREE_TILDE_RULE_REGEX = /(?!\s)(`{3,})$/;
15
17
  function createCodeBlockInputRule(schema, editorAnalyticsAPI) {
16
18
  var rules = getCodeBlockRules(editorAnalyticsAPI, schema);
17
19
  return new _safePlugin.SafePlugin((0, _prosemirrorInputRules.createPlugin)('code-block-input-rule', rules, {
@@ -38,9 +40,7 @@ function getCodeBlockRules(editorAnalyticsAPI, schema) {
38
40
  var validMatchLength = function validMatchLength(match) {
39
41
  return match.length > 0 && match[0].length === 3;
40
42
  };
41
-
42
- // eslint-disable-next-line require-unicode-regexp
43
- var threeTildeRule = (0, _utils.createRule)(/(?!\s)(`{3,})$/, function (state, match, start, end) {
43
+ var threeTildeRule = (0, _utils.createRule)(THREE_TILDE_RULE_REGEX, function (state, match, start, end) {
44
44
  if (!validMatchLength(match)) {
45
45
  return null;
46
46
  }
@@ -16,6 +16,77 @@ var MAX_DETECTION_CHARS = 10000;
16
16
  var MIN_DETECTION_SCORE = 3; // Require at least one medium-confidence signal before auto-selecting.
17
17
  var MIN_SCORE_GAP = 2; // Avoid auto-selecting when top two languages are too close to distinguish.
18
18
 
19
+ // looksLikeJson regexes
20
+ var JSON_START_REGEX = /^[{[]/;
21
+ var JSON_END_REGEX = /[}\]]$/;
22
+
23
+ // html regexes
24
+ var HTML_DOCTYPE_REGEX = /<!doctype\s+html/i;
25
+ var HTML_TAG_REGEX = /<\/?(?:html|head|body|div|span|script|style|section|template)\b/i;
26
+
27
+ // css regexes
28
+ var CSS_AT_RULE_REGEX = /@[\w-]+\s+[^{]+\{/;
29
+ var CSS_SELECTOR_PROPERTY_REGEX = /[.#]?[-_a-zA-Z][-_a-zA-Z0-9\s,.:#>+~*\[\]='"]+\{[^}]*\b(?:color|display|margin|padding|font|background|border|width|height|grid|flex)\s*:/;
30
+ var CSS_PROPERTY_REGEX = /\b(?:color|display|margin|padding|font-size|background|border|width|height)\s*:\s*[^;{}]+;/;
31
+
32
+ // sql regexes
33
+ var SQL_SELECT_FROM_REGEX = /\bSELECT\b[\s\S]+\bFROM\b/i;
34
+ var SQL_DML_REGEX = /\b(?:INSERT\s+INTO|UPDATE\b[\s\S]+\bSET\b|DELETE\s+FROM|CREATE\s+TABLE|ALTER\s+TABLE)\b/i;
35
+ var SQL_CLAUSE_REGEX = /\b(?:JOIN|WHERE|GROUP\s+BY|ORDER\s+BY|LIMIT)\b/i;
36
+
37
+ // typescript regexes
38
+ var TS_INTERFACE_TYPE_REGEX = /\b(?:interface|type)\s+[A-Z_$][\w$]*(?:\s*[=<{])/;
39
+ var TS_IMPORT_EXPORT_TYPE_REGEX = /\bimport\s+type\b|\bexport\s+type\b/;
40
+ var TS_TYPED_VAR_REGEX = /\b(?:const|let|var)\s+[\w$]+\s*:\s*[A-Za-z_$][\w$<>|\[\],\s]*/;
41
+ var TS_RETURN_TYPE_REGEX = /\)\s*:\s*(?:Promise<)?[A-Za-z_$][\w$<>|\[\],\s]*(?:>|\s)?\s*=>?\s*[{;]/;
42
+ var TS_ADVANCED_REGEX = /\b(?:as\s+const|implements\s+[A-Z_$]|enum\s+[A-Z_$])/;
43
+
44
+ // javascript regexes
45
+ var JS_VAR_REGEX = /\b(?:const|let|var)\s+[\w$]+\s*=/;
46
+ var JS_FUNCTION_REGEX = /\bfunction\s*[\w$]*\s*\([^)]*\)\s*\{/;
47
+ var JS_ARROW_REGEX = /=>\s*(?:\{|[\w$'"`(])/;
48
+ var JS_IMPORT_EXPORT_REGEX = /\b(?:import|export)\s+(?:[\w${}*,\s]+\s+from\s+)?['"][^'"]+['"]/;
49
+ var JS_COMMON_API_REGEX = /\b(?:console\.log|document\.|window\.|require\()|\bmodule\.exports\b/;
50
+
51
+ // python regexes
52
+ var PY_DEF_REGEX = /^\s*def\s+[a-zA-Z_]\w*\([^)]*\)\s*:/m;
53
+ var PY_CLASS_REGEX = /^\s*class\s+[A-Z_]\w*(?:\([^)]*\))?\s*:/m;
54
+ var PY_IMPORT_REGEX = /^\s*(?:from\s+[\w.]+\s+import\s+\w+|import\s+[\w.]+)/m;
55
+ var PY_CONTROL_REGEX = /^\s*(?:if|elif|else|for|while|try|except)\b[^\n]*:\s*$/m;
56
+ var PY_PRINT_REGEX = /\bprint\([^)]*\)/;
57
+
58
+ // java regexes
59
+ var JAVA_CLASS_REGEX = /\bpublic\s+(?:final\s+)?class\s+[A-Z]\w*/;
60
+ var JAVA_MAIN_REGEX = /\bpublic\s+static\s+void\s+main\s*\(\s*String\[\]/;
61
+ var JAVA_PRINTLN_REGEX = /\bSystem\.out\.println\s*\(/;
62
+ var JAVA_MEMBER_REGEX = /\b(?:private|protected|public)\s+(?:static\s+)?(?:final\s+)?[A-Z]\w*(?:<[^>]+>)?\s+\w+\s*[;(=]/;
63
+
64
+ // go regexes
65
+ var GO_PACKAGE_REGEX = /^\s*package\s+\w+/m;
66
+ var GO_FUNC_REGEX = /\bfunc\s+(?:\([^)]*\)\s*)?[A-Za-z_]\w*\s*\([^)]*\)\s*(?:[A-Za-z_*\[\]]+\s*)?\{/;
67
+ var GO_PRINTLN_REGEX = /\bfmt\.(?:Println|Printf)\s*\(/;
68
+ var GO_IMPORT_REGEX = /\bimport\s+\(\s*[\s\S]*?\)/;
69
+
70
+ // ruby regexes
71
+ var RUBY_DEF_REGEX = /^\s*def\s+[a-z_]\w*[!?=]?/m;
72
+ var RUBY_CLASS_REGEX = /^\s*class\s+[A-Z]\w*(?:\s*<\s*[A-Z]\w*)?/m;
73
+ var RUBY_END_REGEX = /^\s*end\s*$/m;
74
+ var RUBY_COMMON_API_REGEX = /\b(?:puts|require|attr_reader|attr_accessor)\b/;
75
+ var RUBY_BLOCK_REGEX = /\bdo\s*\|[^|]+\|/;
76
+
77
+ // rust regexes
78
+ var RUST_FN_REGEX = /\bfn\s+[a-z_]\w*\s*\([^)]*\)\s*(?:->\s*[A-Za-z_:<>]+\s*)?\{/;
79
+ var RUST_LET_MUT_REGEX = /\blet\s+mut\s+\w+/;
80
+ var RUST_PRINTLN_REGEX = /\bprintln!\s*\(/;
81
+ var RUST_USE_REGEX = /\buse\s+(?:std|crate|super)::/;
82
+ var RUST_STRUCT_REGEX = /\b(?:impl|pub\s+struct|enum)\s+[A-Z]\w*/;
83
+
84
+ // shell regexes
85
+ var SHELL_SHEBANG_REGEX = /^#!\/usr\/bin\/(?:env\s+)?(?:ba|z|k)?sh\b/m;
86
+ var SHELL_CONTROL_REGEX = /^\s*(?:if|for|while)\b[\s\S]+\b(?:then|do)\b/m;
87
+ var SHELL_FI_DONE_REGEX = /^\s*(?:fi|done)\s*$/m;
88
+ var SHELL_COMMAND_REGEX = /\b(?:echo|export|cd|grep|sed|awk|curl)\b[\s\S]*(?:\$\w+|&&|\|)/;
89
+ var SHELL_VAR_REGEX = /\$\{?[A-Z_][A-Z0-9_]*\}?/;
19
90
  var hasPattern = function hasPattern(code, pattern) {
20
91
  // Reset stateful regexes so repeated tests always start at the beginning.
21
92
  pattern.lastIndex = 0;
@@ -56,7 +127,7 @@ var looksLikeHtmlTagPair = function looksLikeHtmlTagPair(code) {
56
127
  };
57
128
  var looksLikeJson = function looksLikeJson(code) {
58
129
  var trimmed = code.trim();
59
- if (!/^[{[]/.test(trimmed) || !/[}\]]$/.test(trimmed)) {
130
+ if (!JSON_START_REGEX.test(trimmed) || !JSON_END_REGEX.test(trimmed)) {
60
131
  return false;
61
132
  }
62
133
  try {
@@ -72,37 +143,37 @@ var getLanguageScores = function getLanguageScores(code) {
72
143
  score: looksLikeJson(code) ? 8 : 0
73
144
  }, {
74
145
  language: 'html',
75
- score: scorePatterns(code, [[/<!doctype\s+html/i, 5], [/<\/?(?:html|head|body|div|span|script|style|section|template)\b/i, 2]]) + (looksLikeHtmlTagPair(code) ? 3 : 0)
146
+ score: scorePatterns(code, [[HTML_DOCTYPE_REGEX, 5], [HTML_TAG_REGEX, 2]]) + (looksLikeHtmlTagPair(code) ? 3 : 0)
76
147
  }, {
77
148
  language: 'css',
78
- score: scorePatterns(code, [[/@[\w-]+\s+[^{]+\{/, 3], [/[.#]?[-_a-zA-Z][-_a-zA-Z0-9\s,.:#>+~*\[\]='"]+\{[^}]*\b(?:color|display|margin|padding|font|background|border|width|height|grid|flex)\s*:/, 5], [/\b(?:color|display|margin|padding|font-size|background|border|width|height)\s*:\s*[^;{}]+;/, 3]])
149
+ score: scorePatterns(code, [[CSS_AT_RULE_REGEX, 3], [CSS_SELECTOR_PROPERTY_REGEX, 5], [CSS_PROPERTY_REGEX, 3]])
79
150
  }, {
80
151
  language: 'sql',
81
- score: scorePatterns(code, [[/\bSELECT\b[\s\S]+\bFROM\b/i, 5], [/\b(?:INSERT\s+INTO|UPDATE\b[\s\S]+\bSET\b|DELETE\s+FROM|CREATE\s+TABLE|ALTER\s+TABLE)\b/i, 5], [/\b(?:JOIN|WHERE|GROUP\s+BY|ORDER\s+BY|LIMIT)\b/i, 2]])
152
+ score: scorePatterns(code, [[SQL_SELECT_FROM_REGEX, 5], [SQL_DML_REGEX, 5], [SQL_CLAUSE_REGEX, 2]])
82
153
  }, {
83
154
  language: 'typescript',
84
- score: scorePatterns(code, [[/\b(?:interface|type)\s+[A-Z_$][\w$]*(?:\s*[=<{])/, 5], [/\bimport\s+type\b|\bexport\s+type\b/, 4], [/\b(?:const|let|var)\s+[\w$]+\s*:\s*[A-Za-z_$][\w$<>|\[\],\s]*/, 4], [/\)\s*:\s*(?:Promise<)?[A-Za-z_$][\w$<>|\[\],\s]*(?:>|\s)?\s*=>?\s*[{;]/, 3], [/\b(?:as\s+const|implements\s+[A-Z_$]|enum\s+[A-Z_$])/, 3]]) + scoreEnhancedTypeScriptPatterns(code)
155
+ 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]]) + scoreEnhancedTypeScriptPatterns(code)
85
156
  }, {
86
157
  language: 'javascript',
87
- score: scorePatterns(code, [[/\b(?:const|let|var)\s+[\w$]+\s*=/, 3], [/\bfunction\s*[\w$]*\s*\([^)]*\)\s*\{/, 3], [/=>\s*(?:\{|[\w$'"`(])/, 3], [/\b(?:import|export)\s+(?:[\w${}*,\s]+\s+from\s+)?['"][^'"]+['"]/, 3], [/\b(?:console\.log|document\.|window\.|require\()|\bmodule\.exports\b/, 3]])
158
+ 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]])
88
159
  }, {
89
160
  language: 'python',
90
- score: scorePatterns(code, [[/^\s*def\s+[a-zA-Z_]\w*\([^)]*\)\s*:/m, 5], [/^\s*class\s+[A-Z_]\w*(?:\([^)]*\))?\s*:/m, 4], [/^\s*(?:from\s+[\w.]+\s+import\s+\w+|import\s+[\w.]+)/m, 3], [/^\s*(?:if|elif|else|for|while|try|except)\b[^\n]*:\s*$/m, 2], [/\bprint\([^)]*\)/, 2]])
161
+ score: scorePatterns(code, [[PY_DEF_REGEX, 5], [PY_CLASS_REGEX, 4], [PY_IMPORT_REGEX, 3], [PY_CONTROL_REGEX, 2], [PY_PRINT_REGEX, 2]])
91
162
  }, {
92
163
  language: 'java',
93
- score: scorePatterns(code, [[/\bpublic\s+(?:final\s+)?class\s+[A-Z]\w*/, 5], [/\bpublic\s+static\s+void\s+main\s*\(\s*String\[\]/, 5], [/\bSystem\.out\.println\s*\(/, 4], [/\b(?:private|protected|public)\s+(?:static\s+)?(?:final\s+)?[A-Z]\w*(?:<[^>]+>)?\s+\w+\s*[;(=]/, 3]])
164
+ score: scorePatterns(code, [[JAVA_CLASS_REGEX, 5], [JAVA_MAIN_REGEX, 5], [JAVA_PRINTLN_REGEX, 4], [JAVA_MEMBER_REGEX, 3]])
94
165
  }, {
95
166
  language: 'go',
96
- score: scorePatterns(code, [[/^\s*package\s+\w+/m, 5], [/\bfunc\s+(?:\([^)]*\)\s*)?[A-Za-z_]\w*\s*\([^)]*\)\s*(?:[A-Za-z_*\[\]]+\s*)?\{/, 5], [/\bfmt\.(?:Println|Printf)\s*\(/, 3], [/\bimport\s+\(\s*[\s\S]*?\)/, 2]])
167
+ score: scorePatterns(code, [[GO_PACKAGE_REGEX, 5], [GO_FUNC_REGEX, 5], [GO_PRINTLN_REGEX, 3], [GO_IMPORT_REGEX, 2]])
97
168
  }, {
98
169
  language: 'ruby',
99
- score: scorePatterns(code, [[/^\s*def\s+[a-z_]\w*[!?=]?/m, 4], [/^\s*class\s+[A-Z]\w*(?:\s*<\s*[A-Z]\w*)?/m, 3], [/^\s*end\s*$/m, 3], [/\b(?:puts|require|attr_reader|attr_accessor)\b/, 3], [/\bdo\s*\|[^|]+\|/, 2]])
170
+ score: scorePatterns(code, [[RUBY_DEF_REGEX, 4], [RUBY_CLASS_REGEX, 3], [RUBY_END_REGEX, 3], [RUBY_COMMON_API_REGEX, 3], [RUBY_BLOCK_REGEX, 2]])
100
171
  }, {
101
172
  language: 'rust',
102
- score: scorePatterns(code, [[/\bfn\s+[a-z_]\w*\s*\([^)]*\)\s*(?:->\s*[A-Za-z_:<>]+\s*)?\{/, 5], [/\blet\s+mut\s+\w+/, 3], [/\bprintln!\s*\(/, 4], [/\buse\s+(?:std|crate|super)::/, 3], [/\b(?:impl|pub\s+struct|enum)\s+[A-Z]\w*/, 3]])
173
+ score: scorePatterns(code, [[RUST_FN_REGEX, 5], [RUST_LET_MUT_REGEX, 3], [RUST_PRINTLN_REGEX, 4], [RUST_USE_REGEX, 3], [RUST_STRUCT_REGEX, 3]])
103
174
  }, {
104
175
  language: 'shell',
105
- score: scorePatterns(code, [[/^#!\/usr\/bin\/(?:env\s+)?(?:ba|z|k)?sh\b/m, 6], [/^\s*(?:if|for|while)\b[\s\S]+\b(?:then|do)\b/m, 4], [/^\s*(?:fi|done)\s*$/m, 3], [/\b(?:echo|export|cd|grep|sed|awk|curl)\b[\s\S]*(?:\$\w+|&&|\|)/, 3], [/\$\{?[A-Z_][A-Z0-9_]*\}?/, 2]])
176
+ score: scorePatterns(code, [[SHELL_SHEBANG_REGEX, 6], [SHELL_CONTROL_REGEX, 4], [SHELL_FI_DONE_REGEX, 3], [SHELL_COMMAND_REGEX, 3], [SHELL_VAR_REGEX, 2]])
106
177
  }];
107
178
  };
108
179
  var detectLanguage = exports.detectLanguage = function detectLanguage(code) {
@@ -3,18 +3,22 @@ export const BRACKET_MAP = {
3
3
  '[': ']',
4
4
  '(': ')'
5
5
  };
6
+ // when directly before a closing bracket
7
+ // Ignored via go/ees005
8
+ // eslint-disable-next-line require-unicode-regexp
9
+ const CLOSING_BRACKET_REGEX = /^[}\])]/;
10
+ // exclusion: when directly before a non-whitespace character
11
+ // Ignored via go/ees005
12
+ // eslint-disable-next-line require-unicode-regexp
13
+ const NON_WHITESPACE_AFTER_REGEX = /^[^\s]/;
6
14
  export const shouldAutoCloseBracket = (before, after) => {
7
15
  // when directly before a closing bracket
8
- // Ignored via go/ees005
9
- // eslint-disable-next-line require-unicode-regexp
10
- if (/^[}\])]/.test(after)) {
16
+ if (CLOSING_BRACKET_REGEX.test(after)) {
11
17
  return true;
12
18
  }
13
19
 
14
20
  // exclusion: when directly before a non-whitespace character
15
- // Ignored via go/ees005
16
- // eslint-disable-next-line require-unicode-regexp
17
- if (/^[^\s]/.test(after)) {
21
+ if (NON_WHITESPACE_AFTER_REGEX.test(after)) {
18
22
  return false;
19
23
  }
20
24
  return true;
@@ -3,27 +3,34 @@ export const QUOTE_MAP = {
3
3
  '"': '"',
4
4
  '`': '`'
5
5
  };
6
+ // when directly before a closing bracket
7
+ // Ignored via go/ees005
8
+ // eslint-disable-next-line require-unicode-regexp
9
+ const CLOSING_BRACKET_REGEX = /^[}\])]/;
10
+ // exclusion: when directly before a non-whitespace character
11
+ // Ignored via go/ees005
12
+ // eslint-disable-next-line require-unicode-regexp
13
+ const NON_WHITESPACE_AFTER_REGEX = /^[^\s]/;
14
+ // exclusion: when directly after a letter or quote
15
+ // Ignored via go/ees005
16
+ // eslint-disable-next-line require-unicode-regexp
17
+ const ALPHANUMERIC_END_REGEX = /[A-Za-z0-9]$/;
18
+ // Ignored via go/ees005
19
+ // eslint-disable-next-line require-unicode-regexp
20
+ const QUOTE_END_REGEX = /[\'\"\'`]$/;
6
21
  export const shouldAutoCloseQuote = (before, after) => {
7
22
  // when directly before a closing bracket
8
- // Ignored via go/ees005
9
- // eslint-disable-next-line require-unicode-regexp
10
- if (/^[}\])]/.test(after)) {
23
+ if (CLOSING_BRACKET_REGEX.test(after)) {
11
24
  return true;
12
25
  }
13
26
 
14
27
  // exclusion: when directly before a non-whitespace character
15
- // Ignored via go/ees005
16
- // eslint-disable-next-line require-unicode-regexp
17
- if (/^[^\s]/.test(after)) {
28
+ if (NON_WHITESPACE_AFTER_REGEX.test(after)) {
18
29
  return false;
19
30
  }
20
31
 
21
32
  // exclusion: when directly after a letter or quote
22
- // Ignored via go/ees005
23
- // eslint-disable-next-line require-unicode-regexp
24
- // Ignored via go/ees005
25
- // eslint-disable-next-line require-unicode-regexp
26
- if (/[A-Za-z0-9]$/.test(before) || /[\'\"\`]$/.test(before)) {
33
+ if (ALPHANUMERIC_END_REGEX.test(before) || QUOTE_END_REGEX.test(before)) {
27
34
  return false;
28
35
  }
29
36
  return true;
@@ -6,6 +6,9 @@ import { createRule, inputRuleWithAnalytics } from '@atlaskit/editor-common/util
6
6
  import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
7
7
  import { createPlugin, leafNodeReplacementCharacter } from '@atlaskit/prosemirror-input-rules';
8
8
  import { isConvertableToCodeBlock, transformToCodeBlockAction } from './transform-to-code-block';
9
+
10
+ // eslint-disable-next-line require-unicode-regexp
11
+ const THREE_TILDE_RULE_REGEX = /(?!\s)(`{3,})$/;
9
12
  export function createCodeBlockInputRule(schema, editorAnalyticsAPI) {
10
13
  const rules = getCodeBlockRules(editorAnalyticsAPI, schema);
11
14
  return new SafePlugin(createPlugin('code-block-input-rule', rules, {
@@ -30,9 +33,7 @@ function getCodeBlockRules(editorAnalyticsAPI, schema) {
30
33
  eventType: EVENT_TYPE.TRACK
31
34
  }, editorAnalyticsAPI);
32
35
  const validMatchLength = match => match.length > 0 && match[0].length === 3;
33
-
34
- // eslint-disable-next-line require-unicode-regexp
35
- const threeTildeRule = createRule(/(?!\s)(`{3,})$/, (state, match, start, end) => {
36
+ const threeTildeRule = createRule(THREE_TILDE_RULE_REGEX, (state, match, start, end) => {
36
37
  if (!validMatchLength(match)) {
37
38
  return null;
38
39
  }
@@ -6,6 +6,77 @@ const MAX_DETECTION_CHARS = 10_000;
6
6
  const MIN_DETECTION_SCORE = 3; // Require at least one medium-confidence signal before auto-selecting.
7
7
  const MIN_SCORE_GAP = 2; // Avoid auto-selecting when top two languages are too close to distinguish.
8
8
 
9
+ // looksLikeJson regexes
10
+ const JSON_START_REGEX = /^[{[]/;
11
+ const JSON_END_REGEX = /[}\]]$/;
12
+
13
+ // html regexes
14
+ const HTML_DOCTYPE_REGEX = /<!doctype\s+html/i;
15
+ const HTML_TAG_REGEX = /<\/?(?:html|head|body|div|span|script|style|section|template)\b/i;
16
+
17
+ // css regexes
18
+ const CSS_AT_RULE_REGEX = /@[\w-]+\s+[^{]+\{/;
19
+ const CSS_SELECTOR_PROPERTY_REGEX = /[.#]?[-_a-zA-Z][-_a-zA-Z0-9\s,.:#>+~*\[\]='"]+\{[^}]*\b(?:color|display|margin|padding|font|background|border|width|height|grid|flex)\s*:/;
20
+ const CSS_PROPERTY_REGEX = /\b(?:color|display|margin|padding|font-size|background|border|width|height)\s*:\s*[^;{}]+;/;
21
+
22
+ // sql regexes
23
+ const SQL_SELECT_FROM_REGEX = /\bSELECT\b[\s\S]+\bFROM\b/i;
24
+ const SQL_DML_REGEX = /\b(?:INSERT\s+INTO|UPDATE\b[\s\S]+\bSET\b|DELETE\s+FROM|CREATE\s+TABLE|ALTER\s+TABLE)\b/i;
25
+ const SQL_CLAUSE_REGEX = /\b(?:JOIN|WHERE|GROUP\s+BY|ORDER\s+BY|LIMIT)\b/i;
26
+
27
+ // typescript regexes
28
+ const TS_INTERFACE_TYPE_REGEX = /\b(?:interface|type)\s+[A-Z_$][\w$]*(?:\s*[=<{])/;
29
+ const TS_IMPORT_EXPORT_TYPE_REGEX = /\bimport\s+type\b|\bexport\s+type\b/;
30
+ const TS_TYPED_VAR_REGEX = /\b(?:const|let|var)\s+[\w$]+\s*:\s*[A-Za-z_$][\w$<>|\[\],\s]*/;
31
+ const TS_RETURN_TYPE_REGEX = /\)\s*:\s*(?:Promise<)?[A-Za-z_$][\w$<>|\[\],\s]*(?:>|\s)?\s*=>?\s*[{;]/;
32
+ const TS_ADVANCED_REGEX = /\b(?:as\s+const|implements\s+[A-Z_$]|enum\s+[A-Z_$])/;
33
+
34
+ // javascript regexes
35
+ const JS_VAR_REGEX = /\b(?:const|let|var)\s+[\w$]+\s*=/;
36
+ const JS_FUNCTION_REGEX = /\bfunction\s*[\w$]*\s*\([^)]*\)\s*\{/;
37
+ const JS_ARROW_REGEX = /=>\s*(?:\{|[\w$'"`(])/;
38
+ const JS_IMPORT_EXPORT_REGEX = /\b(?:import|export)\s+(?:[\w${}*,\s]+\s+from\s+)?['"][^'"]+['"]/;
39
+ const JS_COMMON_API_REGEX = /\b(?:console\.log|document\.|window\.|require\()|\bmodule\.exports\b/;
40
+
41
+ // python regexes
42
+ const PY_DEF_REGEX = /^\s*def\s+[a-zA-Z_]\w*\([^)]*\)\s*:/m;
43
+ const PY_CLASS_REGEX = /^\s*class\s+[A-Z_]\w*(?:\([^)]*\))?\s*:/m;
44
+ const PY_IMPORT_REGEX = /^\s*(?:from\s+[\w.]+\s+import\s+\w+|import\s+[\w.]+)/m;
45
+ const PY_CONTROL_REGEX = /^\s*(?:if|elif|else|for|while|try|except)\b[^\n]*:\s*$/m;
46
+ const PY_PRINT_REGEX = /\bprint\([^)]*\)/;
47
+
48
+ // java regexes
49
+ const JAVA_CLASS_REGEX = /\bpublic\s+(?:final\s+)?class\s+[A-Z]\w*/;
50
+ const JAVA_MAIN_REGEX = /\bpublic\s+static\s+void\s+main\s*\(\s*String\[\]/;
51
+ const JAVA_PRINTLN_REGEX = /\bSystem\.out\.println\s*\(/;
52
+ const JAVA_MEMBER_REGEX = /\b(?:private|protected|public)\s+(?:static\s+)?(?:final\s+)?[A-Z]\w*(?:<[^>]+>)?\s+\w+\s*[;(=]/;
53
+
54
+ // go regexes
55
+ const GO_PACKAGE_REGEX = /^\s*package\s+\w+/m;
56
+ const GO_FUNC_REGEX = /\bfunc\s+(?:\([^)]*\)\s*)?[A-Za-z_]\w*\s*\([^)]*\)\s*(?:[A-Za-z_*\[\]]+\s*)?\{/;
57
+ const GO_PRINTLN_REGEX = /\bfmt\.(?:Println|Printf)\s*\(/;
58
+ const GO_IMPORT_REGEX = /\bimport\s+\(\s*[\s\S]*?\)/;
59
+
60
+ // ruby regexes
61
+ const RUBY_DEF_REGEX = /^\s*def\s+[a-z_]\w*[!?=]?/m;
62
+ const RUBY_CLASS_REGEX = /^\s*class\s+[A-Z]\w*(?:\s*<\s*[A-Z]\w*)?/m;
63
+ const RUBY_END_REGEX = /^\s*end\s*$/m;
64
+ const RUBY_COMMON_API_REGEX = /\b(?:puts|require|attr_reader|attr_accessor)\b/;
65
+ const RUBY_BLOCK_REGEX = /\bdo\s*\|[^|]+\|/;
66
+
67
+ // rust regexes
68
+ const RUST_FN_REGEX = /\bfn\s+[a-z_]\w*\s*\([^)]*\)\s*(?:->\s*[A-Za-z_:<>]+\s*)?\{/;
69
+ const RUST_LET_MUT_REGEX = /\blet\s+mut\s+\w+/;
70
+ const RUST_PRINTLN_REGEX = /\bprintln!\s*\(/;
71
+ const RUST_USE_REGEX = /\buse\s+(?:std|crate|super)::/;
72
+ const RUST_STRUCT_REGEX = /\b(?:impl|pub\s+struct|enum)\s+[A-Z]\w*/;
73
+
74
+ // shell regexes
75
+ const SHELL_SHEBANG_REGEX = /^#!\/usr\/bin\/(?:env\s+)?(?:ba|z|k)?sh\b/m;
76
+ const SHELL_CONTROL_REGEX = /^\s*(?:if|for|while)\b[\s\S]+\b(?:then|do)\b/m;
77
+ const SHELL_FI_DONE_REGEX = /^\s*(?:fi|done)\s*$/m;
78
+ const SHELL_COMMAND_REGEX = /\b(?:echo|export|cd|grep|sed|awk|curl)\b[\s\S]*(?:\$\w+|&&|\|)/;
79
+ const SHELL_VAR_REGEX = /\$\{?[A-Z_][A-Z0-9_]*\}?/;
9
80
  const hasPattern = (code, pattern) => {
10
81
  // Reset stateful regexes so repeated tests always start at the beginning.
11
82
  pattern.lastIndex = 0;
@@ -34,7 +105,7 @@ const looksLikeHtmlTagPair = code => {
34
105
  };
35
106
  const looksLikeJson = code => {
36
107
  const trimmed = code.trim();
37
- if (!/^[{[]/.test(trimmed) || !/[}\]]$/.test(trimmed)) {
108
+ if (!JSON_START_REGEX.test(trimmed) || !JSON_END_REGEX.test(trimmed)) {
38
109
  return false;
39
110
  }
40
111
  try {
@@ -49,37 +120,37 @@ const getLanguageScores = code => [{
49
120
  score: looksLikeJson(code) ? 8 : 0
50
121
  }, {
51
122
  language: 'html',
52
- score: scorePatterns(code, [[/<!doctype\s+html/i, 5], [/<\/?(?:html|head|body|div|span|script|style|section|template)\b/i, 2]]) + (looksLikeHtmlTagPair(code) ? 3 : 0)
123
+ score: scorePatterns(code, [[HTML_DOCTYPE_REGEX, 5], [HTML_TAG_REGEX, 2]]) + (looksLikeHtmlTagPair(code) ? 3 : 0)
53
124
  }, {
54
125
  language: 'css',
55
- score: scorePatterns(code, [[/@[\w-]+\s+[^{]+\{/, 3], [/[.#]?[-_a-zA-Z][-_a-zA-Z0-9\s,.:#>+~*\[\]='"]+\{[^}]*\b(?:color|display|margin|padding|font|background|border|width|height|grid|flex)\s*:/, 5], [/\b(?:color|display|margin|padding|font-size|background|border|width|height)\s*:\s*[^;{}]+;/, 3]])
126
+ score: scorePatterns(code, [[CSS_AT_RULE_REGEX, 3], [CSS_SELECTOR_PROPERTY_REGEX, 5], [CSS_PROPERTY_REGEX, 3]])
56
127
  }, {
57
128
  language: 'sql',
58
- score: scorePatterns(code, [[/\bSELECT\b[\s\S]+\bFROM\b/i, 5], [/\b(?:INSERT\s+INTO|UPDATE\b[\s\S]+\bSET\b|DELETE\s+FROM|CREATE\s+TABLE|ALTER\s+TABLE)\b/i, 5], [/\b(?:JOIN|WHERE|GROUP\s+BY|ORDER\s+BY|LIMIT)\b/i, 2]])
129
+ score: scorePatterns(code, [[SQL_SELECT_FROM_REGEX, 5], [SQL_DML_REGEX, 5], [SQL_CLAUSE_REGEX, 2]])
59
130
  }, {
60
131
  language: 'typescript',
61
- score: scorePatterns(code, [[/\b(?:interface|type)\s+[A-Z_$][\w$]*(?:\s*[=<{])/, 5], [/\bimport\s+type\b|\bexport\s+type\b/, 4], [/\b(?:const|let|var)\s+[\w$]+\s*:\s*[A-Za-z_$][\w$<>|\[\],\s]*/, 4], [/\)\s*:\s*(?:Promise<)?[A-Za-z_$][\w$<>|\[\],\s]*(?:>|\s)?\s*=>?\s*[{;]/, 3], [/\b(?:as\s+const|implements\s+[A-Z_$]|enum\s+[A-Z_$])/, 3]]) + scoreEnhancedTypeScriptPatterns(code)
132
+ 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]]) + scoreEnhancedTypeScriptPatterns(code)
62
133
  }, {
63
134
  language: 'javascript',
64
- score: scorePatterns(code, [[/\b(?:const|let|var)\s+[\w$]+\s*=/, 3], [/\bfunction\s*[\w$]*\s*\([^)]*\)\s*\{/, 3], [/=>\s*(?:\{|[\w$'"`(])/, 3], [/\b(?:import|export)\s+(?:[\w${}*,\s]+\s+from\s+)?['"][^'"]+['"]/, 3], [/\b(?:console\.log|document\.|window\.|require\()|\bmodule\.exports\b/, 3]])
135
+ 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]])
65
136
  }, {
66
137
  language: 'python',
67
- score: scorePatterns(code, [[/^\s*def\s+[a-zA-Z_]\w*\([^)]*\)\s*:/m, 5], [/^\s*class\s+[A-Z_]\w*(?:\([^)]*\))?\s*:/m, 4], [/^\s*(?:from\s+[\w.]+\s+import\s+\w+|import\s+[\w.]+)/m, 3], [/^\s*(?:if|elif|else|for|while|try|except)\b[^\n]*:\s*$/m, 2], [/\bprint\([^)]*\)/, 2]])
138
+ score: scorePatterns(code, [[PY_DEF_REGEX, 5], [PY_CLASS_REGEX, 4], [PY_IMPORT_REGEX, 3], [PY_CONTROL_REGEX, 2], [PY_PRINT_REGEX, 2]])
68
139
  }, {
69
140
  language: 'java',
70
- score: scorePatterns(code, [[/\bpublic\s+(?:final\s+)?class\s+[A-Z]\w*/, 5], [/\bpublic\s+static\s+void\s+main\s*\(\s*String\[\]/, 5], [/\bSystem\.out\.println\s*\(/, 4], [/\b(?:private|protected|public)\s+(?:static\s+)?(?:final\s+)?[A-Z]\w*(?:<[^>]+>)?\s+\w+\s*[;(=]/, 3]])
141
+ score: scorePatterns(code, [[JAVA_CLASS_REGEX, 5], [JAVA_MAIN_REGEX, 5], [JAVA_PRINTLN_REGEX, 4], [JAVA_MEMBER_REGEX, 3]])
71
142
  }, {
72
143
  language: 'go',
73
- score: scorePatterns(code, [[/^\s*package\s+\w+/m, 5], [/\bfunc\s+(?:\([^)]*\)\s*)?[A-Za-z_]\w*\s*\([^)]*\)\s*(?:[A-Za-z_*\[\]]+\s*)?\{/, 5], [/\bfmt\.(?:Println|Printf)\s*\(/, 3], [/\bimport\s+\(\s*[\s\S]*?\)/, 2]])
144
+ score: scorePatterns(code, [[GO_PACKAGE_REGEX, 5], [GO_FUNC_REGEX, 5], [GO_PRINTLN_REGEX, 3], [GO_IMPORT_REGEX, 2]])
74
145
  }, {
75
146
  language: 'ruby',
76
- score: scorePatterns(code, [[/^\s*def\s+[a-z_]\w*[!?=]?/m, 4], [/^\s*class\s+[A-Z]\w*(?:\s*<\s*[A-Z]\w*)?/m, 3], [/^\s*end\s*$/m, 3], [/\b(?:puts|require|attr_reader|attr_accessor)\b/, 3], [/\bdo\s*\|[^|]+\|/, 2]])
147
+ score: scorePatterns(code, [[RUBY_DEF_REGEX, 4], [RUBY_CLASS_REGEX, 3], [RUBY_END_REGEX, 3], [RUBY_COMMON_API_REGEX, 3], [RUBY_BLOCK_REGEX, 2]])
77
148
  }, {
78
149
  language: 'rust',
79
- score: scorePatterns(code, [[/\bfn\s+[a-z_]\w*\s*\([^)]*\)\s*(?:->\s*[A-Za-z_:<>]+\s*)?\{/, 5], [/\blet\s+mut\s+\w+/, 3], [/\bprintln!\s*\(/, 4], [/\buse\s+(?:std|crate|super)::/, 3], [/\b(?:impl|pub\s+struct|enum)\s+[A-Z]\w*/, 3]])
150
+ score: scorePatterns(code, [[RUST_FN_REGEX, 5], [RUST_LET_MUT_REGEX, 3], [RUST_PRINTLN_REGEX, 4], [RUST_USE_REGEX, 3], [RUST_STRUCT_REGEX, 3]])
80
151
  }, {
81
152
  language: 'shell',
82
- score: scorePatterns(code, [[/^#!\/usr\/bin\/(?:env\s+)?(?:ba|z|k)?sh\b/m, 6], [/^\s*(?:if|for|while)\b[\s\S]+\b(?:then|do)\b/m, 4], [/^\s*(?:fi|done)\s*$/m, 3], [/\b(?:echo|export|cd|grep|sed|awk|curl)\b[\s\S]*(?:\$\w+|&&|\|)/, 3], [/\$\{?[A-Z_][A-Z0-9_]*\}?/, 2]])
153
+ score: scorePatterns(code, [[SHELL_SHEBANG_REGEX, 6], [SHELL_CONTROL_REGEX, 4], [SHELL_FI_DONE_REGEX, 3], [SHELL_COMMAND_REGEX, 3], [SHELL_VAR_REGEX, 2]])
83
154
  }];
84
155
  export const detectLanguage = code => {
85
156
  const trimmedCode = code.trim();
@@ -3,18 +3,22 @@ export var BRACKET_MAP = {
3
3
  '[': ']',
4
4
  '(': ')'
5
5
  };
6
+ // when directly before a closing bracket
7
+ // Ignored via go/ees005
8
+ // eslint-disable-next-line require-unicode-regexp
9
+ var CLOSING_BRACKET_REGEX = /^[}\])]/;
10
+ // exclusion: when directly before a non-whitespace character
11
+ // Ignored via go/ees005
12
+ // eslint-disable-next-line require-unicode-regexp
13
+ var NON_WHITESPACE_AFTER_REGEX = /^[^\s]/;
6
14
  export var shouldAutoCloseBracket = function shouldAutoCloseBracket(before, after) {
7
15
  // when directly before a closing bracket
8
- // Ignored via go/ees005
9
- // eslint-disable-next-line require-unicode-regexp
10
- if (/^[}\])]/.test(after)) {
16
+ if (CLOSING_BRACKET_REGEX.test(after)) {
11
17
  return true;
12
18
  }
13
19
 
14
20
  // exclusion: when directly before a non-whitespace character
15
- // Ignored via go/ees005
16
- // eslint-disable-next-line require-unicode-regexp
17
- if (/^[^\s]/.test(after)) {
21
+ if (NON_WHITESPACE_AFTER_REGEX.test(after)) {
18
22
  return false;
19
23
  }
20
24
  return true;
@@ -3,27 +3,34 @@ export var QUOTE_MAP = {
3
3
  '"': '"',
4
4
  '`': '`'
5
5
  };
6
+ // when directly before a closing bracket
7
+ // Ignored via go/ees005
8
+ // eslint-disable-next-line require-unicode-regexp
9
+ var CLOSING_BRACKET_REGEX = /^[}\])]/;
10
+ // exclusion: when directly before a non-whitespace character
11
+ // Ignored via go/ees005
12
+ // eslint-disable-next-line require-unicode-regexp
13
+ var NON_WHITESPACE_AFTER_REGEX = /^[^\s]/;
14
+ // exclusion: when directly after a letter or quote
15
+ // Ignored via go/ees005
16
+ // eslint-disable-next-line require-unicode-regexp
17
+ var ALPHANUMERIC_END_REGEX = /[A-Za-z0-9]$/;
18
+ // Ignored via go/ees005
19
+ // eslint-disable-next-line require-unicode-regexp
20
+ var QUOTE_END_REGEX = /[\'\"\'`]$/;
6
21
  export var shouldAutoCloseQuote = function shouldAutoCloseQuote(before, after) {
7
22
  // when directly before a closing bracket
8
- // Ignored via go/ees005
9
- // eslint-disable-next-line require-unicode-regexp
10
- if (/^[}\])]/.test(after)) {
23
+ if (CLOSING_BRACKET_REGEX.test(after)) {
11
24
  return true;
12
25
  }
13
26
 
14
27
  // exclusion: when directly before a non-whitespace character
15
- // Ignored via go/ees005
16
- // eslint-disable-next-line require-unicode-regexp
17
- if (/^[^\s]/.test(after)) {
28
+ if (NON_WHITESPACE_AFTER_REGEX.test(after)) {
18
29
  return false;
19
30
  }
20
31
 
21
32
  // exclusion: when directly after a letter or quote
22
- // Ignored via go/ees005
23
- // eslint-disable-next-line require-unicode-regexp
24
- // Ignored via go/ees005
25
- // eslint-disable-next-line require-unicode-regexp
26
- if (/[A-Za-z0-9]$/.test(before) || /[\'\"\`]$/.test(before)) {
33
+ if (ALPHANUMERIC_END_REGEX.test(before) || QUOTE_END_REGEX.test(before)) {
27
34
  return false;
28
35
  }
29
36
  return true;
@@ -6,6 +6,9 @@ import { createRule, inputRuleWithAnalytics } from '@atlaskit/editor-common/util
6
6
  import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
7
7
  import { createPlugin, leafNodeReplacementCharacter } from '@atlaskit/prosemirror-input-rules';
8
8
  import { isConvertableToCodeBlock, transformToCodeBlockAction } from './transform-to-code-block';
9
+
10
+ // eslint-disable-next-line require-unicode-regexp
11
+ var THREE_TILDE_RULE_REGEX = /(?!\s)(`{3,})$/;
9
12
  export function createCodeBlockInputRule(schema, editorAnalyticsAPI) {
10
13
  var rules = getCodeBlockRules(editorAnalyticsAPI, schema);
11
14
  return new SafePlugin(createPlugin('code-block-input-rule', rules, {
@@ -32,9 +35,7 @@ function getCodeBlockRules(editorAnalyticsAPI, schema) {
32
35
  var validMatchLength = function validMatchLength(match) {
33
36
  return match.length > 0 && match[0].length === 3;
34
37
  };
35
-
36
- // eslint-disable-next-line require-unicode-regexp
37
- var threeTildeRule = createRule(/(?!\s)(`{3,})$/, function (state, match, start, end) {
38
+ var threeTildeRule = createRule(THREE_TILDE_RULE_REGEX, function (state, match, start, end) {
38
39
  if (!validMatchLength(match)) {
39
40
  return null;
40
41
  }
@@ -8,6 +8,77 @@ var MAX_DETECTION_CHARS = 10000;
8
8
  var MIN_DETECTION_SCORE = 3; // Require at least one medium-confidence signal before auto-selecting.
9
9
  var MIN_SCORE_GAP = 2; // Avoid auto-selecting when top two languages are too close to distinguish.
10
10
 
11
+ // looksLikeJson regexes
12
+ var JSON_START_REGEX = /^[{[]/;
13
+ var JSON_END_REGEX = /[}\]]$/;
14
+
15
+ // html regexes
16
+ var HTML_DOCTYPE_REGEX = /<!doctype\s+html/i;
17
+ var HTML_TAG_REGEX = /<\/?(?:html|head|body|div|span|script|style|section|template)\b/i;
18
+
19
+ // css regexes
20
+ var CSS_AT_RULE_REGEX = /@[\w-]+\s+[^{]+\{/;
21
+ var CSS_SELECTOR_PROPERTY_REGEX = /[.#]?[-_a-zA-Z][-_a-zA-Z0-9\s,.:#>+~*\[\]='"]+\{[^}]*\b(?:color|display|margin|padding|font|background|border|width|height|grid|flex)\s*:/;
22
+ var CSS_PROPERTY_REGEX = /\b(?:color|display|margin|padding|font-size|background|border|width|height)\s*:\s*[^;{}]+;/;
23
+
24
+ // sql regexes
25
+ var SQL_SELECT_FROM_REGEX = /\bSELECT\b[\s\S]+\bFROM\b/i;
26
+ var SQL_DML_REGEX = /\b(?:INSERT\s+INTO|UPDATE\b[\s\S]+\bSET\b|DELETE\s+FROM|CREATE\s+TABLE|ALTER\s+TABLE)\b/i;
27
+ var SQL_CLAUSE_REGEX = /\b(?:JOIN|WHERE|GROUP\s+BY|ORDER\s+BY|LIMIT)\b/i;
28
+
29
+ // typescript regexes
30
+ var TS_INTERFACE_TYPE_REGEX = /\b(?:interface|type)\s+[A-Z_$][\w$]*(?:\s*[=<{])/;
31
+ var TS_IMPORT_EXPORT_TYPE_REGEX = /\bimport\s+type\b|\bexport\s+type\b/;
32
+ var TS_TYPED_VAR_REGEX = /\b(?:const|let|var)\s+[\w$]+\s*:\s*[A-Za-z_$][\w$<>|\[\],\s]*/;
33
+ var TS_RETURN_TYPE_REGEX = /\)\s*:\s*(?:Promise<)?[A-Za-z_$][\w$<>|\[\],\s]*(?:>|\s)?\s*=>?\s*[{;]/;
34
+ var TS_ADVANCED_REGEX = /\b(?:as\s+const|implements\s+[A-Z_$]|enum\s+[A-Z_$])/;
35
+
36
+ // javascript regexes
37
+ var JS_VAR_REGEX = /\b(?:const|let|var)\s+[\w$]+\s*=/;
38
+ var JS_FUNCTION_REGEX = /\bfunction\s*[\w$]*\s*\([^)]*\)\s*\{/;
39
+ var JS_ARROW_REGEX = /=>\s*(?:\{|[\w$'"`(])/;
40
+ var JS_IMPORT_EXPORT_REGEX = /\b(?:import|export)\s+(?:[\w${}*,\s]+\s+from\s+)?['"][^'"]+['"]/;
41
+ var JS_COMMON_API_REGEX = /\b(?:console\.log|document\.|window\.|require\()|\bmodule\.exports\b/;
42
+
43
+ // python regexes
44
+ var PY_DEF_REGEX = /^\s*def\s+[a-zA-Z_]\w*\([^)]*\)\s*:/m;
45
+ var PY_CLASS_REGEX = /^\s*class\s+[A-Z_]\w*(?:\([^)]*\))?\s*:/m;
46
+ var PY_IMPORT_REGEX = /^\s*(?:from\s+[\w.]+\s+import\s+\w+|import\s+[\w.]+)/m;
47
+ var PY_CONTROL_REGEX = /^\s*(?:if|elif|else|for|while|try|except)\b[^\n]*:\s*$/m;
48
+ var PY_PRINT_REGEX = /\bprint\([^)]*\)/;
49
+
50
+ // java regexes
51
+ var JAVA_CLASS_REGEX = /\bpublic\s+(?:final\s+)?class\s+[A-Z]\w*/;
52
+ var JAVA_MAIN_REGEX = /\bpublic\s+static\s+void\s+main\s*\(\s*String\[\]/;
53
+ var JAVA_PRINTLN_REGEX = /\bSystem\.out\.println\s*\(/;
54
+ var JAVA_MEMBER_REGEX = /\b(?:private|protected|public)\s+(?:static\s+)?(?:final\s+)?[A-Z]\w*(?:<[^>]+>)?\s+\w+\s*[;(=]/;
55
+
56
+ // go regexes
57
+ var GO_PACKAGE_REGEX = /^\s*package\s+\w+/m;
58
+ var GO_FUNC_REGEX = /\bfunc\s+(?:\([^)]*\)\s*)?[A-Za-z_]\w*\s*\([^)]*\)\s*(?:[A-Za-z_*\[\]]+\s*)?\{/;
59
+ var GO_PRINTLN_REGEX = /\bfmt\.(?:Println|Printf)\s*\(/;
60
+ var GO_IMPORT_REGEX = /\bimport\s+\(\s*[\s\S]*?\)/;
61
+
62
+ // ruby regexes
63
+ var RUBY_DEF_REGEX = /^\s*def\s+[a-z_]\w*[!?=]?/m;
64
+ var RUBY_CLASS_REGEX = /^\s*class\s+[A-Z]\w*(?:\s*<\s*[A-Z]\w*)?/m;
65
+ var RUBY_END_REGEX = /^\s*end\s*$/m;
66
+ var RUBY_COMMON_API_REGEX = /\b(?:puts|require|attr_reader|attr_accessor)\b/;
67
+ var RUBY_BLOCK_REGEX = /\bdo\s*\|[^|]+\|/;
68
+
69
+ // rust regexes
70
+ var RUST_FN_REGEX = /\bfn\s+[a-z_]\w*\s*\([^)]*\)\s*(?:->\s*[A-Za-z_:<>]+\s*)?\{/;
71
+ var RUST_LET_MUT_REGEX = /\blet\s+mut\s+\w+/;
72
+ var RUST_PRINTLN_REGEX = /\bprintln!\s*\(/;
73
+ var RUST_USE_REGEX = /\buse\s+(?:std|crate|super)::/;
74
+ var RUST_STRUCT_REGEX = /\b(?:impl|pub\s+struct|enum)\s+[A-Z]\w*/;
75
+
76
+ // shell regexes
77
+ var SHELL_SHEBANG_REGEX = /^#!\/usr\/bin\/(?:env\s+)?(?:ba|z|k)?sh\b/m;
78
+ var SHELL_CONTROL_REGEX = /^\s*(?:if|for|while)\b[\s\S]+\b(?:then|do)\b/m;
79
+ var SHELL_FI_DONE_REGEX = /^\s*(?:fi|done)\s*$/m;
80
+ var SHELL_COMMAND_REGEX = /\b(?:echo|export|cd|grep|sed|awk|curl)\b[\s\S]*(?:\$\w+|&&|\|)/;
81
+ var SHELL_VAR_REGEX = /\$\{?[A-Z_][A-Z0-9_]*\}?/;
11
82
  var hasPattern = function hasPattern(code, pattern) {
12
83
  // Reset stateful regexes so repeated tests always start at the beginning.
13
84
  pattern.lastIndex = 0;
@@ -48,7 +119,7 @@ var looksLikeHtmlTagPair = function looksLikeHtmlTagPair(code) {
48
119
  };
49
120
  var looksLikeJson = function looksLikeJson(code) {
50
121
  var trimmed = code.trim();
51
- if (!/^[{[]/.test(trimmed) || !/[}\]]$/.test(trimmed)) {
122
+ if (!JSON_START_REGEX.test(trimmed) || !JSON_END_REGEX.test(trimmed)) {
52
123
  return false;
53
124
  }
54
125
  try {
@@ -64,37 +135,37 @@ var getLanguageScores = function getLanguageScores(code) {
64
135
  score: looksLikeJson(code) ? 8 : 0
65
136
  }, {
66
137
  language: 'html',
67
- score: scorePatterns(code, [[/<!doctype\s+html/i, 5], [/<\/?(?:html|head|body|div|span|script|style|section|template)\b/i, 2]]) + (looksLikeHtmlTagPair(code) ? 3 : 0)
138
+ score: scorePatterns(code, [[HTML_DOCTYPE_REGEX, 5], [HTML_TAG_REGEX, 2]]) + (looksLikeHtmlTagPair(code) ? 3 : 0)
68
139
  }, {
69
140
  language: 'css',
70
- score: scorePatterns(code, [[/@[\w-]+\s+[^{]+\{/, 3], [/[.#]?[-_a-zA-Z][-_a-zA-Z0-9\s,.:#>+~*\[\]='"]+\{[^}]*\b(?:color|display|margin|padding|font|background|border|width|height|grid|flex)\s*:/, 5], [/\b(?:color|display|margin|padding|font-size|background|border|width|height)\s*:\s*[^;{}]+;/, 3]])
141
+ score: scorePatterns(code, [[CSS_AT_RULE_REGEX, 3], [CSS_SELECTOR_PROPERTY_REGEX, 5], [CSS_PROPERTY_REGEX, 3]])
71
142
  }, {
72
143
  language: 'sql',
73
- score: scorePatterns(code, [[/\bSELECT\b[\s\S]+\bFROM\b/i, 5], [/\b(?:INSERT\s+INTO|UPDATE\b[\s\S]+\bSET\b|DELETE\s+FROM|CREATE\s+TABLE|ALTER\s+TABLE)\b/i, 5], [/\b(?:JOIN|WHERE|GROUP\s+BY|ORDER\s+BY|LIMIT)\b/i, 2]])
144
+ score: scorePatterns(code, [[SQL_SELECT_FROM_REGEX, 5], [SQL_DML_REGEX, 5], [SQL_CLAUSE_REGEX, 2]])
74
145
  }, {
75
146
  language: 'typescript',
76
- score: scorePatterns(code, [[/\b(?:interface|type)\s+[A-Z_$][\w$]*(?:\s*[=<{])/, 5], [/\bimport\s+type\b|\bexport\s+type\b/, 4], [/\b(?:const|let|var)\s+[\w$]+\s*:\s*[A-Za-z_$][\w$<>|\[\],\s]*/, 4], [/\)\s*:\s*(?:Promise<)?[A-Za-z_$][\w$<>|\[\],\s]*(?:>|\s)?\s*=>?\s*[{;]/, 3], [/\b(?:as\s+const|implements\s+[A-Z_$]|enum\s+[A-Z_$])/, 3]]) + scoreEnhancedTypeScriptPatterns(code)
147
+ 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]]) + scoreEnhancedTypeScriptPatterns(code)
77
148
  }, {
78
149
  language: 'javascript',
79
- score: scorePatterns(code, [[/\b(?:const|let|var)\s+[\w$]+\s*=/, 3], [/\bfunction\s*[\w$]*\s*\([^)]*\)\s*\{/, 3], [/=>\s*(?:\{|[\w$'"`(])/, 3], [/\b(?:import|export)\s+(?:[\w${}*,\s]+\s+from\s+)?['"][^'"]+['"]/, 3], [/\b(?:console\.log|document\.|window\.|require\()|\bmodule\.exports\b/, 3]])
150
+ 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]])
80
151
  }, {
81
152
  language: 'python',
82
- score: scorePatterns(code, [[/^\s*def\s+[a-zA-Z_]\w*\([^)]*\)\s*:/m, 5], [/^\s*class\s+[A-Z_]\w*(?:\([^)]*\))?\s*:/m, 4], [/^\s*(?:from\s+[\w.]+\s+import\s+\w+|import\s+[\w.]+)/m, 3], [/^\s*(?:if|elif|else|for|while|try|except)\b[^\n]*:\s*$/m, 2], [/\bprint\([^)]*\)/, 2]])
153
+ score: scorePatterns(code, [[PY_DEF_REGEX, 5], [PY_CLASS_REGEX, 4], [PY_IMPORT_REGEX, 3], [PY_CONTROL_REGEX, 2], [PY_PRINT_REGEX, 2]])
83
154
  }, {
84
155
  language: 'java',
85
- score: scorePatterns(code, [[/\bpublic\s+(?:final\s+)?class\s+[A-Z]\w*/, 5], [/\bpublic\s+static\s+void\s+main\s*\(\s*String\[\]/, 5], [/\bSystem\.out\.println\s*\(/, 4], [/\b(?:private|protected|public)\s+(?:static\s+)?(?:final\s+)?[A-Z]\w*(?:<[^>]+>)?\s+\w+\s*[;(=]/, 3]])
156
+ score: scorePatterns(code, [[JAVA_CLASS_REGEX, 5], [JAVA_MAIN_REGEX, 5], [JAVA_PRINTLN_REGEX, 4], [JAVA_MEMBER_REGEX, 3]])
86
157
  }, {
87
158
  language: 'go',
88
- score: scorePatterns(code, [[/^\s*package\s+\w+/m, 5], [/\bfunc\s+(?:\([^)]*\)\s*)?[A-Za-z_]\w*\s*\([^)]*\)\s*(?:[A-Za-z_*\[\]]+\s*)?\{/, 5], [/\bfmt\.(?:Println|Printf)\s*\(/, 3], [/\bimport\s+\(\s*[\s\S]*?\)/, 2]])
159
+ score: scorePatterns(code, [[GO_PACKAGE_REGEX, 5], [GO_FUNC_REGEX, 5], [GO_PRINTLN_REGEX, 3], [GO_IMPORT_REGEX, 2]])
89
160
  }, {
90
161
  language: 'ruby',
91
- score: scorePatterns(code, [[/^\s*def\s+[a-z_]\w*[!?=]?/m, 4], [/^\s*class\s+[A-Z]\w*(?:\s*<\s*[A-Z]\w*)?/m, 3], [/^\s*end\s*$/m, 3], [/\b(?:puts|require|attr_reader|attr_accessor)\b/, 3], [/\bdo\s*\|[^|]+\|/, 2]])
162
+ score: scorePatterns(code, [[RUBY_DEF_REGEX, 4], [RUBY_CLASS_REGEX, 3], [RUBY_END_REGEX, 3], [RUBY_COMMON_API_REGEX, 3], [RUBY_BLOCK_REGEX, 2]])
92
163
  }, {
93
164
  language: 'rust',
94
- score: scorePatterns(code, [[/\bfn\s+[a-z_]\w*\s*\([^)]*\)\s*(?:->\s*[A-Za-z_:<>]+\s*)?\{/, 5], [/\blet\s+mut\s+\w+/, 3], [/\bprintln!\s*\(/, 4], [/\buse\s+(?:std|crate|super)::/, 3], [/\b(?:impl|pub\s+struct|enum)\s+[A-Z]\w*/, 3]])
165
+ score: scorePatterns(code, [[RUST_FN_REGEX, 5], [RUST_LET_MUT_REGEX, 3], [RUST_PRINTLN_REGEX, 4], [RUST_USE_REGEX, 3], [RUST_STRUCT_REGEX, 3]])
95
166
  }, {
96
167
  language: 'shell',
97
- score: scorePatterns(code, [[/^#!\/usr\/bin\/(?:env\s+)?(?:ba|z|k)?sh\b/m, 6], [/^\s*(?:if|for|while)\b[\s\S]+\b(?:then|do)\b/m, 4], [/^\s*(?:fi|done)\s*$/m, 3], [/\b(?:echo|export|cd|grep|sed|awk|curl)\b[\s\S]*(?:\$\w+|&&|\|)/, 3], [/\$\{?[A-Z_][A-Z0-9_]*\}?/, 2]])
168
+ score: scorePatterns(code, [[SHELL_SHEBANG_REGEX, 6], [SHELL_CONTROL_REGEX, 4], [SHELL_FI_DONE_REGEX, 3], [SHELL_COMMAND_REGEX, 3], [SHELL_VAR_REGEX, 2]])
98
169
  }];
99
170
  };
100
171
  export var detectLanguage = function detectLanguage(code) {
@@ -6,7 +6,7 @@ export declare const BRACKET_MAP: {
6
6
  export type BracketMapKey = keyof typeof BRACKET_MAP;
7
7
  export declare const shouldAutoCloseBracket: (before: string, after: string) => boolean;
8
8
  export declare const getAutoClosingBracketInfo: (before: string, after: string) => {
9
+ hasTrailingMatchingBracket: boolean;
9
10
  left: "{" | "[" | "(" | undefined;
10
11
  right: string | undefined;
11
- hasTrailingMatchingBracket: boolean;
12
12
  };
@@ -6,7 +6,7 @@ export declare const QUOTE_MAP: {
6
6
  export type QuoteMapKey = keyof typeof QUOTE_MAP;
7
7
  export declare const shouldAutoCloseQuote: (before: string, after: string) => boolean;
8
8
  export declare const getAutoClosingQuoteInfo: (before: string, after: string) => {
9
+ hasTrailingMatchingQuote: boolean;
9
10
  left: "'" | "\"" | "`" | undefined;
10
11
  right: string | undefined;
11
- hasTrailingMatchingQuote: boolean;
12
12
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-code-block",
3
- "version": "14.1.5",
3
+ "version": "14.1.7",
4
4
  "description": "Code block plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -20,7 +20,7 @@
20
20
  "atlaskit:src": "src/index.ts",
21
21
  "dependencies": {
22
22
  "@atlaskit/adf-schema": "^56.0.0",
23
- "@atlaskit/button": "^24.2.0",
23
+ "@atlaskit/button": "^24.3.0",
24
24
  "@atlaskit/code": "^18.2.0",
25
25
  "@atlaskit/css": "^1.0.0",
26
26
  "@atlaskit/editor-plugin-analytics": "^12.0.0",
@@ -39,16 +39,16 @@
39
39
  "@atlaskit/frontend-utilities": "^4.1.0",
40
40
  "@atlaskit/icon": "^36.1.0",
41
41
  "@atlaskit/platform-feature-flags": "^2.0.0",
42
- "@atlaskit/primitives": "^20.1.0",
42
+ "@atlaskit/primitives": "^20.2.0",
43
43
  "@atlaskit/prosemirror-input-rules": "^4.0.0",
44
44
  "@atlaskit/select": "^22.2.0",
45
- "@atlaskit/tmp-editor-statsig": "^114.0.0",
46
- "@atlaskit/tokens": "^15.1.0",
45
+ "@atlaskit/tmp-editor-statsig": "^115.0.0",
46
+ "@atlaskit/tokens": "^15.2.0",
47
47
  "@babel/runtime": "^7.0.0",
48
48
  "@compiled/react": "^0.20.0"
49
49
  },
50
50
  "peerDependencies": {
51
- "@atlaskit/editor-common": "^116.15.0",
51
+ "@atlaskit/editor-common": "^116.17.0",
52
52
  "react": "^18.2.0",
53
53
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
54
54
  },