@atlaskit/editor-plugin-code-block 0.1.0

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.
Files changed (126) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/LICENSE.md +13 -0
  3. package/README.md +30 -0
  4. package/dist/cjs/actions.js +201 -0
  5. package/dist/cjs/ide-ux/bracket-handling.js +35 -0
  6. package/dist/cjs/ide-ux/commands.js +115 -0
  7. package/dist/cjs/ide-ux/line-handling.js +81 -0
  8. package/dist/cjs/ide-ux/paired-character-handling.js +23 -0
  9. package/dist/cjs/ide-ux/quote-handling.js +40 -0
  10. package/dist/cjs/index.js +13 -0
  11. package/dist/cjs/language-list.js +62 -0
  12. package/dist/cjs/nodeviews/code-block.js +153 -0
  13. package/dist/cjs/plugin-key.js +8 -0
  14. package/dist/cjs/plugin.js +120 -0
  15. package/dist/cjs/pm-plugins/actions.js +10 -0
  16. package/dist/cjs/pm-plugins/codeBlockCopySelectionPlugin.js +113 -0
  17. package/dist/cjs/pm-plugins/ide-ux.js +132 -0
  18. package/dist/cjs/pm-plugins/input-rule.js +68 -0
  19. package/dist/cjs/pm-plugins/keymaps.js +66 -0
  20. package/dist/cjs/pm-plugins/main-state.js +10 -0
  21. package/dist/cjs/pm-plugins/main.js +114 -0
  22. package/dist/cjs/refresh-browser-selection.js +29 -0
  23. package/dist/cjs/toolbar.js +131 -0
  24. package/dist/cjs/transform-to-code-block.js +84 -0
  25. package/dist/cjs/types.js +5 -0
  26. package/dist/cjs/ui/class-names.js +15 -0
  27. package/dist/cjs/utils.js +28 -0
  28. package/dist/es2019/actions.js +211 -0
  29. package/dist/es2019/ide-ux/bracket-handling.js +27 -0
  30. package/dist/es2019/ide-ux/commands.js +115 -0
  31. package/dist/es2019/ide-ux/line-handling.js +75 -0
  32. package/dist/es2019/ide-ux/paired-character-handling.js +12 -0
  33. package/dist/es2019/ide-ux/quote-handling.js +32 -0
  34. package/dist/es2019/index.js +1 -0
  35. package/dist/es2019/language-list.js +51 -0
  36. package/dist/es2019/nodeviews/code-block.js +126 -0
  37. package/dist/es2019/plugin-key.js +2 -0
  38. package/dist/es2019/plugin.js +104 -0
  39. package/dist/es2019/pm-plugins/actions.js +4 -0
  40. package/dist/es2019/pm-plugins/codeBlockCopySelectionPlugin.js +101 -0
  41. package/dist/es2019/pm-plugins/ide-ux.js +135 -0
  42. package/dist/es2019/pm-plugins/input-rule.js +60 -0
  43. package/dist/es2019/pm-plugins/keymaps.js +58 -0
  44. package/dist/es2019/pm-plugins/main-state.js +2 -0
  45. package/dist/es2019/pm-plugins/main.js +102 -0
  46. package/dist/es2019/refresh-browser-selection.js +25 -0
  47. package/dist/es2019/toolbar.js +108 -0
  48. package/dist/es2019/transform-to-code-block.js +79 -0
  49. package/dist/es2019/types.js +1 -0
  50. package/dist/es2019/ui/class-names.js +9 -0
  51. package/dist/es2019/utils.js +4 -0
  52. package/dist/esm/actions.js +191 -0
  53. package/dist/esm/ide-ux/bracket-handling.js +29 -0
  54. package/dist/esm/ide-ux/commands.js +107 -0
  55. package/dist/esm/ide-ux/line-handling.js +73 -0
  56. package/dist/esm/ide-ux/paired-character-handling.js +16 -0
  57. package/dist/esm/ide-ux/quote-handling.js +34 -0
  58. package/dist/esm/index.js +1 -0
  59. package/dist/esm/language-list.js +52 -0
  60. package/dist/esm/nodeviews/code-block.js +146 -0
  61. package/dist/esm/plugin-key.js +2 -0
  62. package/dist/esm/plugin.js +113 -0
  63. package/dist/esm/pm-plugins/actions.js +4 -0
  64. package/dist/esm/pm-plugins/codeBlockCopySelectionPlugin.js +103 -0
  65. package/dist/esm/pm-plugins/ide-ux.js +126 -0
  66. package/dist/esm/pm-plugins/input-rule.js +62 -0
  67. package/dist/esm/pm-plugins/keymaps.js +59 -0
  68. package/dist/esm/pm-plugins/main-state.js +4 -0
  69. package/dist/esm/pm-plugins/main.js +107 -0
  70. package/dist/esm/refresh-browser-selection.js +25 -0
  71. package/dist/esm/toolbar.js +121 -0
  72. package/dist/esm/transform-to-code-block.js +77 -0
  73. package/dist/esm/types.js +1 -0
  74. package/dist/esm/ui/class-names.js +9 -0
  75. package/dist/esm/utils.js +4 -0
  76. package/dist/types/actions.d.ts +18 -0
  77. package/dist/types/ide-ux/bracket-handling.d.ts +12 -0
  78. package/dist/types/ide-ux/commands.d.ts +7 -0
  79. package/dist/types/ide-ux/line-handling.d.ts +25 -0
  80. package/dist/types/ide-ux/paired-character-handling.d.ts +2 -0
  81. package/dist/types/ide-ux/quote-handling.d.ts +12 -0
  82. package/dist/types/index.d.ts +3 -0
  83. package/dist/types/language-list.d.ts +942 -0
  84. package/dist/types/nodeviews/code-block.d.ts +21 -0
  85. package/dist/types/plugin-key.d.ts +2 -0
  86. package/dist/types/plugin.d.ts +19 -0
  87. package/dist/types/pm-plugins/actions.d.ts +4 -0
  88. package/dist/types/pm-plugins/codeBlockCopySelectionPlugin.d.ts +11 -0
  89. package/dist/types/pm-plugins/ide-ux.d.ts +5 -0
  90. package/dist/types/pm-plugins/input-rule.d.ts +3 -0
  91. package/dist/types/pm-plugins/keymaps.d.ts +4 -0
  92. package/dist/types/pm-plugins/main-state.d.ts +8 -0
  93. package/dist/types/pm-plugins/main.d.ts +10 -0
  94. package/dist/types/refresh-browser-selection.d.ts +5 -0
  95. package/dist/types/toolbar.d.ts +14 -0
  96. package/dist/types/transform-to-code-block.d.ts +3 -0
  97. package/dist/types/types.d.ts +6 -0
  98. package/dist/types/ui/class-names.d.ts +8 -0
  99. package/dist/types/utils.d.ts +4 -0
  100. package/dist/types-ts4.5/actions.d.ts +18 -0
  101. package/dist/types-ts4.5/ide-ux/bracket-handling.d.ts +12 -0
  102. package/dist/types-ts4.5/ide-ux/commands.d.ts +7 -0
  103. package/dist/types-ts4.5/ide-ux/line-handling.d.ts +25 -0
  104. package/dist/types-ts4.5/ide-ux/paired-character-handling.d.ts +2 -0
  105. package/dist/types-ts4.5/ide-ux/quote-handling.d.ts +12 -0
  106. package/dist/types-ts4.5/index.d.ts +3 -0
  107. package/dist/types-ts4.5/language-list.d.ts +1641 -0
  108. package/dist/types-ts4.5/nodeviews/code-block.d.ts +21 -0
  109. package/dist/types-ts4.5/plugin-key.d.ts +2 -0
  110. package/dist/types-ts4.5/plugin.d.ts +19 -0
  111. package/dist/types-ts4.5/pm-plugins/actions.d.ts +4 -0
  112. package/dist/types-ts4.5/pm-plugins/codeBlockCopySelectionPlugin.d.ts +14 -0
  113. package/dist/types-ts4.5/pm-plugins/ide-ux.d.ts +5 -0
  114. package/dist/types-ts4.5/pm-plugins/input-rule.d.ts +3 -0
  115. package/dist/types-ts4.5/pm-plugins/keymaps.d.ts +4 -0
  116. package/dist/types-ts4.5/pm-plugins/main-state.d.ts +8 -0
  117. package/dist/types-ts4.5/pm-plugins/main.d.ts +10 -0
  118. package/dist/types-ts4.5/refresh-browser-selection.d.ts +5 -0
  119. package/dist/types-ts4.5/toolbar.d.ts +14 -0
  120. package/dist/types-ts4.5/transform-to-code-block.d.ts +3 -0
  121. package/dist/types-ts4.5/types.d.ts +6 -0
  122. package/dist/types-ts4.5/ui/class-names.d.ts +8 -0
  123. package/dist/types-ts4.5/utils.d.ts +4 -0
  124. package/package.json +99 -0
  125. package/report.api.md +73 -0
  126. package/tmp/api-report-tmp.d.ts +45 -0
@@ -0,0 +1,191 @@
1
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
2
+ import { copyToClipboard } from '@atlaskit/editor-common/clipboard';
3
+ import { withAnalytics } from '@atlaskit/editor-common/editor-analytics';
4
+ import { shouldSplitSelectedNodeOnNodeInsertion } from '@atlaskit/editor-common/insert';
5
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
6
+ import { findParentNodeOfType, findSelectedNodeOfType, isNodeSelection, removeParentNodeOfType, removeSelectedNode, safeInsert } from '@atlaskit/editor-prosemirror/utils';
7
+ import { pluginKey } from './plugin-key';
8
+ import { ACTIONS } from './pm-plugins/actions';
9
+ import { copySelectionPluginKey } from './pm-plugins/codeBlockCopySelectionPlugin';
10
+ import { transformToCodeBlockAction } from './transform-to-code-block';
11
+ export var removeCodeBlock = function removeCodeBlock(state, dispatch) {
12
+ var nodes = state.schema.nodes,
13
+ tr = state.tr;
14
+ if (dispatch) {
15
+ var removeTr = tr;
16
+ if (findSelectedNodeOfType(nodes.codeBlock)(tr.selection)) {
17
+ removeTr = removeSelectedNode(tr);
18
+ } else {
19
+ removeTr = removeParentNodeOfType(nodes.codeBlock)(tr);
20
+ }
21
+ dispatch(removeTr);
22
+ }
23
+ return true;
24
+ };
25
+ export var changeLanguage = function changeLanguage(editorAnalyticsAPI) {
26
+ return function (language) {
27
+ return function (state, dispatch) {
28
+ var _pluginKey$getState;
29
+ var codeBlock = state.schema.nodes.codeBlock;
30
+ var pos = (_pluginKey$getState = pluginKey.getState(state)) === null || _pluginKey$getState === void 0 ? void 0 : _pluginKey$getState.pos;
31
+ if (typeof pos !== 'number') {
32
+ return false;
33
+ }
34
+ var tr = state.tr.setNodeMarkup(pos, codeBlock, {
35
+ language: language
36
+ }).setMeta('scrollIntoView', false);
37
+ var selection = isNodeSelection(state.selection) ? NodeSelection.create(tr.doc, pos) : tr.selection;
38
+ var result = tr.setSelection(selection);
39
+ if (dispatch) {
40
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({
41
+ action: ACTION.LANGUAGE_SELECTED,
42
+ actionSubject: ACTION_SUBJECT.CODE_BLOCK,
43
+ attributes: {
44
+ language: language
45
+ },
46
+ eventType: EVENT_TYPE.TRACK
47
+ })(result);
48
+ dispatch(result);
49
+ }
50
+ return true;
51
+ };
52
+ };
53
+ };
54
+ export var copyContentToClipboard = function copyContentToClipboard(state, dispatch) {
55
+ var nodes = state.schema.nodes,
56
+ tr = state.tr;
57
+ var codeBlock = findParentNodeOfType(nodes.codeBlock)(tr.selection);
58
+ var textContent = codeBlock && codeBlock.node.textContent;
59
+ if (textContent) {
60
+ copyToClipboard(textContent);
61
+ var copyToClipboardTr = tr;
62
+ copyToClipboardTr.setMeta(pluginKey, {
63
+ type: ACTIONS.SET_COPIED_TO_CLIPBOARD,
64
+ data: true
65
+ });
66
+ copyToClipboardTr.setMeta(copySelectionPluginKey, 'remove-selection');
67
+ if (dispatch) {
68
+ dispatch(copyToClipboardTr);
69
+ }
70
+ }
71
+ return true;
72
+ };
73
+ export var resetCopiedState = function resetCopiedState(state, dispatch) {
74
+ var tr = state.tr;
75
+ var codeBlockState = pluginKey.getState(state);
76
+ var resetCopiedStateTr = tr;
77
+ if (codeBlockState && codeBlockState.contentCopied) {
78
+ resetCopiedStateTr.setMeta(pluginKey, {
79
+ type: ACTIONS.SET_COPIED_TO_CLIPBOARD,
80
+ data: false
81
+ });
82
+ resetCopiedStateTr.setMeta(copySelectionPluginKey, 'remove-selection');
83
+ if (dispatch) {
84
+ dispatch(resetCopiedStateTr);
85
+ }
86
+ } else {
87
+ var clearSelectionStateTransaction = state.tr;
88
+ clearSelectionStateTransaction.setMeta(copySelectionPluginKey, 'remove-selection');
89
+ // note: dispatch should always be defined when called from the
90
+ // floating toolbar. Howver the Command type which floating toolbar uses
91
+ // (and resetCopiedState) uses suggests it's optional.
92
+ if (dispatch) {
93
+ dispatch(clearSelectionStateTransaction);
94
+ }
95
+ }
96
+ return true;
97
+ };
98
+ export var ignoreFollowingMutations = function ignoreFollowingMutations(state, dispatch) {
99
+ var tr = state.tr;
100
+ var ignoreFollowingMutationsTr = tr;
101
+ ignoreFollowingMutationsTr.setMeta(pluginKey, {
102
+ type: ACTIONS.SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS,
103
+ data: true
104
+ });
105
+ if (dispatch) {
106
+ dispatch(ignoreFollowingMutationsTr);
107
+ }
108
+ return true;
109
+ };
110
+ export var resetShouldIgnoreFollowingMutations = function resetShouldIgnoreFollowingMutations(state, dispatch) {
111
+ var tr = state.tr;
112
+ var ignoreFollowingMutationsTr = tr;
113
+ ignoreFollowingMutationsTr.setMeta(pluginKey, {
114
+ type: ACTIONS.SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS,
115
+ data: false
116
+ });
117
+ if (dispatch) {
118
+ dispatch(ignoreFollowingMutationsTr);
119
+ }
120
+ return true;
121
+ };
122
+
123
+ /**
124
+ * This function creates a new transaction that inserts a code block,
125
+ * if there is text selected it will wrap the current selection if not it will
126
+ * append the codeblock to the end of the document.
127
+ */
128
+ export function createInsertCodeBlockTransaction(_ref) {
129
+ var _state$selection$$fro;
130
+ var state = _ref.state;
131
+ var tr = state.tr;
132
+ var from = state.selection.from;
133
+ var codeBlock = state.schema.nodes.codeBlock;
134
+ var grandParentNodeType = (_state$selection$$fro = state.selection.$from.node(-1)) === null || _state$selection$$fro === void 0 ? void 0 : _state$selection$$fro.type;
135
+ var parentNodeType = state.selection.$from.parent.type;
136
+
137
+ /** We always want to append a codeBlock unless we're inserting into a paragraph
138
+ * AND it's a valid child of the grandparent node.
139
+ * Insert the current selection as codeBlock content unless it contains nodes other
140
+ * than paragraphs and inline.
141
+ */
142
+ var canInsertCodeBlock = shouldSplitSelectedNodeOnNodeInsertion({
143
+ parentNodeType: parentNodeType,
144
+ grandParentNodeType: grandParentNodeType,
145
+ content: codeBlock.createAndFill()
146
+ }) && contentAllowedInCodeBlock(state);
147
+ if (canInsertCodeBlock) {
148
+ tr = transformToCodeBlockAction(state, from);
149
+ } else {
150
+ safeInsert(codeBlock.createAndFill())(tr).scrollIntoView();
151
+ }
152
+ return tr;
153
+ }
154
+
155
+ /**
156
+ * Check if the current selection contains any nodes that are not permitted
157
+ * as codeBlock child nodes. Note that this allows paragraphs and inline nodes
158
+ * as we extract their text content.
159
+ */
160
+ function contentAllowedInCodeBlock(state) {
161
+ var _state$selection = state.selection,
162
+ $from = _state$selection.$from,
163
+ $to = _state$selection.$to;
164
+ var isAllowedChild = true;
165
+ state.doc.nodesBetween($from.pos, $to.pos, function (node) {
166
+ if (!isAllowedChild) {
167
+ return false;
168
+ }
169
+ return isAllowedChild = node.type === state.schema.nodes.listItem || node.type === state.schema.nodes.bulletList || node.type === state.schema.nodes.orderedList || node.type === state.schema.nodes.paragraph || node.isInline || node.isText;
170
+ });
171
+ return isAllowedChild;
172
+ }
173
+ export function insertCodeBlockWithAnalytics(inputMethod, analyticsAPI) {
174
+ return withAnalytics(analyticsAPI, {
175
+ action: ACTION.INSERTED,
176
+ actionSubject: ACTION_SUBJECT.DOCUMENT,
177
+ actionSubjectId: ACTION_SUBJECT_ID.CODE_BLOCK,
178
+ attributes: {
179
+ inputMethod: inputMethod
180
+ },
181
+ eventType: EVENT_TYPE.TRACK
182
+ })(function (state, dispatch) {
183
+ var tr = createInsertCodeBlockTransaction({
184
+ state: state
185
+ });
186
+ if (dispatch) {
187
+ dispatch(tr);
188
+ }
189
+ return true;
190
+ });
191
+ }
@@ -0,0 +1,29 @@
1
+ export var BRACKET_MAP = {
2
+ '{': '}',
3
+ '[': ']',
4
+ '(': ')'
5
+ };
6
+ export var shouldAutoCloseBracket = function shouldAutoCloseBracket(before, after) {
7
+ // when directly before a closing bracket
8
+ if (/^[}\])]/.test(after)) {
9
+ return true;
10
+ }
11
+
12
+ // exclusion: when directly before a non-whitespace character
13
+ if (/^[^\s]/.test(after)) {
14
+ return false;
15
+ }
16
+ return true;
17
+ };
18
+ export var getAutoClosingBracketInfo = function getAutoClosingBracketInfo(before, after) {
19
+ var left = Object.keys(BRACKET_MAP).find(function (item) {
20
+ return before.endsWith(item);
21
+ });
22
+ var right = left ? BRACKET_MAP[left] : undefined;
23
+ var hasTrailingMatchingBracket = right ? after.startsWith(right) : false;
24
+ return {
25
+ left: left,
26
+ right: right,
27
+ hasTrailingMatchingBracket: hasTrailingMatchingBracket
28
+ };
29
+ };
@@ -0,0 +1,107 @@
1
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INDENT_DIRECTION, INDENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
+ import { TextSelection } from '@atlaskit/editor-prosemirror/state';
3
+ import { forEachLine, getLineInfo, getLinesFromSelection, getStartOfCurrentLine } from './line-handling';
4
+
5
+ /**
6
+ * Return the current indentation level
7
+ * @param indentText - Text in the code block that represent an indentation
8
+ * @param indentSize - Size of the indentation token in a string
9
+ */
10
+ function getIndentLevel(indentText, indentSize) {
11
+ if (indentSize === 0 || indentText.length === 0) {
12
+ return 0;
13
+ }
14
+ return indentText.length / indentSize;
15
+ }
16
+ export var indent = function indent(editorAnalyticsAPI) {
17
+ return function (state, dispatch) {
18
+ var _getLinesFromSelectio = getLinesFromSelection(state),
19
+ text = _getLinesFromSelectio.text,
20
+ start = _getLinesFromSelectio.start;
21
+ var tr = state.tr,
22
+ selection = state.selection;
23
+ forEachLine(text, function (line, offset) {
24
+ var _getLineInfo = getLineInfo(line),
25
+ indentText = _getLineInfo.indentText,
26
+ indentToken = _getLineInfo.indentToken;
27
+ var indentLevel = getIndentLevel(indentText, indentToken.size);
28
+ var indentToAdd = indentToken.token.repeat(indentToken.size - indentText.length % indentToken.size || indentToken.size);
29
+ tr.insertText(indentToAdd, tr.mapping.map(start + offset, -1));
30
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({
31
+ action: ACTION.FORMATTED,
32
+ actionSubject: ACTION_SUBJECT.TEXT,
33
+ actionSubjectId: ACTION_SUBJECT_ID.FORMAT_INDENT,
34
+ eventType: EVENT_TYPE.TRACK,
35
+ attributes: {
36
+ inputMethod: INPUT_METHOD.KEYBOARD,
37
+ previousIndentationLevel: indentLevel,
38
+ newIndentLevel: indentLevel + 1,
39
+ direction: INDENT_DIRECTION.INDENT,
40
+ indentType: INDENT_TYPE.CODE_BLOCK
41
+ }
42
+ })(tr);
43
+ if (!selection.empty) {
44
+ tr.setSelection(TextSelection.create(tr.doc, tr.mapping.map(selection.from, -1), tr.selection.to));
45
+ }
46
+ });
47
+ if (dispatch) {
48
+ dispatch(tr);
49
+ }
50
+ return true;
51
+ };
52
+ };
53
+ export var outdent = function outdent(editorAnalyticsAPI) {
54
+ return function (state, dispatch) {
55
+ var _getLinesFromSelectio2 = getLinesFromSelection(state),
56
+ text = _getLinesFromSelectio2.text,
57
+ start = _getLinesFromSelectio2.start;
58
+ var tr = state.tr;
59
+ forEachLine(text, function (line, offset) {
60
+ var _getLineInfo2 = getLineInfo(line),
61
+ indentText = _getLineInfo2.indentText,
62
+ indentToken = _getLineInfo2.indentToken;
63
+ if (indentText) {
64
+ var indentLevel = getIndentLevel(indentText, indentToken.size);
65
+ var unindentLength = indentText.length % indentToken.size || indentToken.size;
66
+ tr.delete(tr.mapping.map(start + offset), tr.mapping.map(start + offset + unindentLength));
67
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({
68
+ action: ACTION.FORMATTED,
69
+ actionSubject: ACTION_SUBJECT.TEXT,
70
+ actionSubjectId: ACTION_SUBJECT_ID.FORMAT_INDENT,
71
+ eventType: EVENT_TYPE.TRACK,
72
+ attributes: {
73
+ inputMethod: INPUT_METHOD.KEYBOARD,
74
+ previousIndentationLevel: indentLevel,
75
+ newIndentLevel: indentLevel - 1,
76
+ direction: INDENT_DIRECTION.OUTDENT,
77
+ indentType: INDENT_TYPE.CODE_BLOCK
78
+ }
79
+ })(tr);
80
+ }
81
+ });
82
+ if (dispatch) {
83
+ dispatch(tr);
84
+ }
85
+ return true;
86
+ };
87
+ };
88
+ export function insertIndent(state, dispatch) {
89
+ var _getStartOfCurrentLin = getStartOfCurrentLine(state),
90
+ textAtStartOfLine = _getStartOfCurrentLin.text;
91
+ var _getLineInfo3 = getLineInfo(textAtStartOfLine),
92
+ indentToken = _getLineInfo3.indentToken;
93
+ var indentToAdd = indentToken.token.repeat(indentToken.size - textAtStartOfLine.length % indentToken.size || indentToken.size);
94
+ dispatch(state.tr.insertText(indentToAdd));
95
+ return true;
96
+ }
97
+ export function insertNewlineWithIndent(state, dispatch) {
98
+ var _getStartOfCurrentLin2 = getStartOfCurrentLine(state),
99
+ textAtStartOfLine = _getStartOfCurrentLin2.text;
100
+ var _getLineInfo4 = getLineInfo(textAtStartOfLine),
101
+ indentText = _getLineInfo4.indentText;
102
+ if (indentText && dispatch) {
103
+ dispatch(state.tr.insertText('\n' + indentText));
104
+ return true;
105
+ }
106
+ return false;
107
+ }
@@ -0,0 +1,73 @@
1
+ import { getCursor } from '../utils';
2
+ export var isSelectionEntirelyInsideCodeBlock = function isSelectionEntirelyInsideCodeBlock(state) {
3
+ return state.selection.$from.sameParent(state.selection.$to) && state.selection.$from.parent.type === state.schema.nodes.codeBlock;
4
+ };
5
+ export var isCursorInsideCodeBlock = function isCursorInsideCodeBlock(state) {
6
+ return !!getCursor(state.selection) && isSelectionEntirelyInsideCodeBlock(state);
7
+ };
8
+ export var getStartOfCurrentLine = function getStartOfCurrentLine(state) {
9
+ var $from = state.selection.$from;
10
+ if ($from.nodeBefore && $from.nodeBefore.isText) {
11
+ var prevNewLineIndex = $from.nodeBefore.text.lastIndexOf('\n');
12
+ return {
13
+ text: $from.nodeBefore.text.substring(prevNewLineIndex + 1),
14
+ pos: $from.start() + prevNewLineIndex + 1
15
+ };
16
+ }
17
+ return {
18
+ text: '',
19
+ pos: $from.pos
20
+ };
21
+ };
22
+ export var getEndOfCurrentLine = function getEndOfCurrentLine(state) {
23
+ var $to = state.selection.$to;
24
+ if ($to.nodeAfter && $to.nodeAfter.isText) {
25
+ var nextNewLineIndex = $to.nodeAfter.text.indexOf('\n');
26
+ return {
27
+ text: $to.nodeAfter.text.substring(0, nextNewLineIndex >= 0 ? nextNewLineIndex : undefined),
28
+ pos: nextNewLineIndex >= 0 ? $to.pos + nextNewLineIndex : $to.end()
29
+ };
30
+ }
31
+ return {
32
+ text: '',
33
+ pos: $to.pos
34
+ };
35
+ };
36
+ export function getLinesFromSelection(state) {
37
+ var _getStartOfCurrentLin = getStartOfCurrentLine(state),
38
+ start = _getStartOfCurrentLin.pos;
39
+ var _getEndOfCurrentLine = getEndOfCurrentLine(state),
40
+ end = _getEndOfCurrentLine.pos;
41
+ var text = state.doc.textBetween(start, end);
42
+ return {
43
+ text: text,
44
+ start: start,
45
+ end: end
46
+ };
47
+ }
48
+ export var forEachLine = function forEachLine(text, callback) {
49
+ var offset = 0;
50
+ text.split('\n').forEach(function (line) {
51
+ callback(line, offset);
52
+ offset += line.length + 1;
53
+ });
54
+ };
55
+ var SPACE = {
56
+ token: ' ',
57
+ size: 2,
58
+ regex: /[^ ]/
59
+ };
60
+ var TAB = {
61
+ token: '\t',
62
+ size: 1,
63
+ regex: /[^\t]/
64
+ };
65
+ export var getLineInfo = function getLineInfo(line) {
66
+ var indentToken = line.startsWith('\t') ? TAB : SPACE;
67
+ var indentLength = line.search(indentToken.regex);
68
+ var indentText = line.substring(0, indentLength >= 0 ? indentLength : line.length);
69
+ return {
70
+ indentToken: indentToken,
71
+ indentText: indentText
72
+ };
73
+ };
@@ -0,0 +1,16 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ import { BRACKET_MAP } from './bracket-handling';
5
+ import { QUOTE_MAP } from './quote-handling';
6
+ var PAIRED_CHARACTER_MAP = _objectSpread(_objectSpread({}, BRACKET_MAP), QUOTE_MAP);
7
+ export var isCursorBeforeClosingCharacter = function isCursorBeforeClosingCharacter(after) {
8
+ return Object.keys(PAIRED_CHARACTER_MAP).some(function (leftCharacter) {
9
+ return after.startsWith(PAIRED_CHARACTER_MAP[leftCharacter]);
10
+ });
11
+ };
12
+ export var isClosingCharacter = function isClosingCharacter(text) {
13
+ return Object.keys(PAIRED_CHARACTER_MAP).some(function (leftCharacter) {
14
+ return text === PAIRED_CHARACTER_MAP[leftCharacter];
15
+ });
16
+ };
@@ -0,0 +1,34 @@
1
+ export var QUOTE_MAP = {
2
+ "'": "'",
3
+ '"': '"',
4
+ '`': '`'
5
+ };
6
+ export var shouldAutoCloseQuote = function shouldAutoCloseQuote(before, after) {
7
+ // when directly before a closing bracket
8
+ if (/^[}\])]/.test(after)) {
9
+ return true;
10
+ }
11
+
12
+ // exclusion: when directly before a non-whitespace character
13
+ if (/^[^\s]/.test(after)) {
14
+ return false;
15
+ }
16
+
17
+ // exclusion: when directly after a letter or quote
18
+ if (/[A-Za-z0-9]$/.test(before) || /[\'\"\`]$/.test(before)) {
19
+ return false;
20
+ }
21
+ return true;
22
+ };
23
+ export var getAutoClosingQuoteInfo = function getAutoClosingQuoteInfo(before, after) {
24
+ var left = Object.keys(QUOTE_MAP).find(function (item) {
25
+ return before.endsWith(item);
26
+ });
27
+ var right = left ? QUOTE_MAP[left] : undefined;
28
+ var hasTrailingMatchingQuote = right ? after.startsWith(right) : false;
29
+ return {
30
+ left: left,
31
+ right: right,
32
+ hasTrailingMatchingQuote: hasTrailingMatchingQuote
33
+ };
34
+ };
@@ -0,0 +1 @@
1
+ export { default as codeBlockPlugin } from './plugin';
@@ -0,0 +1,52 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import { SUPPORTED_LANGUAGES } from '@atlaskit/code/constants';
3
+
4
+ // We expect alias[0] to be used for the ADF attribute, see ED-2813
5
+ export var DEFAULT_LANGUAGES = [{
6
+ name: '(None)',
7
+ alias: ['none'],
8
+ value: 'none'
9
+ }].concat(_toConsumableArray(SUPPORTED_LANGUAGES));
10
+ export function findMatchedLanguage(supportedLanguages, language) {
11
+ if (!language) {
12
+ return undefined;
13
+ }
14
+ var matches = supportedLanguages.filter(function (supportedLanguage) {
15
+ return supportedLanguage.alias.indexOf(language.toLowerCase()) !== -1;
16
+ });
17
+ if (matches.length > 0) {
18
+ return matches[0];
19
+ }
20
+ return undefined;
21
+ }
22
+ export function filterSupportedLanguages(supportedLanguages) {
23
+ if (!supportedLanguages || !supportedLanguages.length) {
24
+ return DEFAULT_LANGUAGES;
25
+ }
26
+ return DEFAULT_LANGUAGES.filter(function (language) {
27
+ var i = language.alias.length;
28
+ while (i--) {
29
+ if (supportedLanguages.indexOf(language.alias[i]) > -1) {
30
+ return true;
31
+ }
32
+ }
33
+ return false;
34
+ });
35
+ }
36
+ export function getLanguageIdentifier(language) {
37
+ return language.alias[0];
38
+ }
39
+ export function createLanguageList(supportedLanguages) {
40
+ return supportedLanguages.sort(function (left, right) {
41
+ if (left.alias[0] === 'none') {
42
+ return -1;
43
+ }
44
+ if (left.name.toLowerCase() > right.name.toLowerCase()) {
45
+ return 1;
46
+ }
47
+ if (left.name.toLowerCase() < right.name.toLowerCase()) {
48
+ return -1;
49
+ }
50
+ return 0;
51
+ });
52
+ }
@@ -0,0 +1,146 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
3
+ import _createClass from "@babel/runtime/helpers/createClass";
4
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
5
+ import rafSchedule from 'raf-schd';
6
+ import { browser } from '@atlaskit/editor-common/utils';
7
+ import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
8
+ import { resetShouldIgnoreFollowingMutations } from '../actions';
9
+ import { getPluginState } from '../pm-plugins/main-state';
10
+ import { codeBlockClassNames } from '../ui/class-names';
11
+ var MATCH_NEWLINES = new RegExp('\n', 'g');
12
+ var toDOM = function toDOM(node) {
13
+ return ['div', {
14
+ class: 'code-block'
15
+ }, ['div', {
16
+ class: codeBlockClassNames.start,
17
+ contenteditable: 'false'
18
+ }], ['div', {
19
+ class: codeBlockClassNames.contentWrapper
20
+ }, ['div', {
21
+ class: codeBlockClassNames.gutter,
22
+ contenteditable: 'false'
23
+ }], ['div', {
24
+ class: codeBlockClassNames.content
25
+ }, ['code', {
26
+ 'data-language': node.attrs.language || '',
27
+ spellcheck: 'false',
28
+ contenteditable: 'true',
29
+ 'data-testid': 'code-block--code'
30
+ }, 0]]], ['div', {
31
+ class: codeBlockClassNames.end,
32
+ contenteditable: 'false'
33
+ }]];
34
+ };
35
+ export var CodeBlockView = /*#__PURE__*/function () {
36
+ function CodeBlockView(_node, view, getPos) {
37
+ var _this = this;
38
+ _classCallCheck(this, CodeBlockView);
39
+ _defineProperty(this, "ensureLineNumbers", rafSchedule(function () {
40
+ var lines = 1;
41
+ _this.node.forEach(function (node) {
42
+ var text = node.text;
43
+ if (text) {
44
+ lines += (node.text.match(MATCH_NEWLINES) || []).length;
45
+ }
46
+ });
47
+ while (_this.lineNumberGutter.childElementCount < lines) {
48
+ _this.lineNumberGutter.appendChild(document.createElement('span'));
49
+ }
50
+ while (_this.lineNumberGutter.childElementCount > lines) {
51
+ _this.lineNumberGutter.removeChild(_this.lineNumberGutter.lastChild);
52
+ }
53
+ }));
54
+ var _DOMSerializer$render = DOMSerializer.renderSpec(document, toDOM(_node)),
55
+ dom = _DOMSerializer$render.dom,
56
+ contentDOM = _DOMSerializer$render.contentDOM;
57
+ this.getPos = getPos;
58
+ this.view = view;
59
+ this.node = _node;
60
+ this.dom = dom;
61
+ this.contentDOM = contentDOM;
62
+ this.lineNumberGutter = this.dom.querySelector(".".concat(codeBlockClassNames.gutter));
63
+ this.ensureLineNumbers();
64
+ }
65
+ _createClass(CodeBlockView, [{
66
+ key: "updateDOMAndSelection",
67
+ value: function updateDOMAndSelection(savedInnerHTML, newCursorPosition) {
68
+ var _this$dom;
69
+ if ((_this$dom = this.dom) !== null && _this$dom !== void 0 && _this$dom.childNodes && this.dom.childNodes.length > 1) {
70
+ var _contentView$childNod;
71
+ var contentWrapper = this.dom.childNodes[1];
72
+ var contentView = contentWrapper === null || contentWrapper === void 0 ? void 0 : contentWrapper.childNodes[1];
73
+ if ((contentView === null || contentView === void 0 || (_contentView$childNod = contentView.childNodes) === null || _contentView$childNod === void 0 ? void 0 : _contentView$childNod.length) > 0) {
74
+ var codeElement = contentView.firstChild;
75
+ codeElement.innerHTML = savedInnerHTML;
76
+
77
+ // We need to set cursor for the DOM update
78
+ var textElement = _toConsumableArray(codeElement.childNodes).find(function (child) {
79
+ return child.nodeName === '#text';
80
+ });
81
+ var sel = window.getSelection();
82
+ var range = document.createRange();
83
+ range.setStart(textElement, newCursorPosition);
84
+ range.collapse(true);
85
+ sel === null || sel === void 0 || sel.removeAllRanges();
86
+ sel === null || sel === void 0 || sel.addRange(range);
87
+ }
88
+ }
89
+ }
90
+ }, {
91
+ key: "coalesceDOMElements",
92
+ value: function coalesceDOMElements() {
93
+ var _this$dom2;
94
+ if ((_this$dom2 = this.dom) !== null && _this$dom2 !== void 0 && _this$dom2.childNodes && this.dom.childNodes.length > 1) {
95
+ var contentWrapper = this.dom.childNodes[1];
96
+ var contentView = contentWrapper === null || contentWrapper === void 0 ? void 0 : contentWrapper.childNodes[1];
97
+ if (contentView !== null && contentView !== void 0 && contentView.childNodes && contentView.childNodes.length > 1) {
98
+ var savedInnerHTML = '';
99
+ while (contentView.childNodes.length > 1) {
100
+ var lastChild = contentView.lastChild;
101
+ savedInnerHTML = lastChild.innerHTML + savedInnerHTML;
102
+ contentView.removeChild(lastChild);
103
+ }
104
+ var firstChild = contentView.firstChild;
105
+ savedInnerHTML = firstChild.innerHTML + '\n' + savedInnerHTML;
106
+ var newCursorPosition = firstChild.innerHTML.length + 1;
107
+ setTimeout(this.updateDOMAndSelection.bind(this, savedInnerHTML, newCursorPosition), 20);
108
+ }
109
+ }
110
+ }
111
+ }, {
112
+ key: "update",
113
+ value: function update(node) {
114
+ if (node.type !== this.node.type) {
115
+ return false;
116
+ }
117
+ if (node !== this.node) {
118
+ if (node.attrs.language !== this.node.attrs.language) {
119
+ this.contentDOM.setAttribute('data-language', node.attrs.language || '');
120
+ }
121
+ this.node = node;
122
+ this.ensureLineNumbers();
123
+ if (browser.android) {
124
+ this.coalesceDOMElements();
125
+ resetShouldIgnoreFollowingMutations(this.view.state, this.view.dispatch);
126
+ }
127
+ }
128
+ return true;
129
+ }
130
+ }, {
131
+ key: "ignoreMutation",
132
+ value: function ignoreMutation(record) {
133
+ var pluginState = getPluginState(this.view.state);
134
+ if (pluginState !== null && pluginState !== void 0 && pluginState.shouldIgnoreFollowingMutations) {
135
+ return true;
136
+ }
137
+
138
+ // Ensure updating the line-number gutter doesn't trigger reparsing the codeblock
139
+ return record.target === this.lineNumberGutter || record.target.parentNode === this.lineNumberGutter;
140
+ }
141
+ }]);
142
+ return CodeBlockView;
143
+ }();
144
+ export var codeBlockNodeView = function codeBlockNodeView(node, view, getPos) {
145
+ return new CodeBlockView(node, view, getPos);
146
+ };
@@ -0,0 +1,2 @@
1
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
2
+ export var pluginKey = new PluginKey('codeBlockPlugin');