@atlaskit/editor-plugin-code-block-advanced 3.0.7 → 3.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.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/codeBlockAdvancedPlugin.js +6 -2
- package/dist/cjs/nodeviews/codeBlockAdvanced.js +12 -4
- package/dist/cjs/nodeviews/codeBlockNodeWithToDOMFixed.js +5 -4
- package/dist/cjs/nodeviews/extensions/foldGutter.js +100 -0
- package/dist/cjs/ui/theme.js +31 -1
- package/dist/es2019/codeBlockAdvancedPlugin.js +6 -2
- package/dist/es2019/nodeviews/codeBlockAdvanced.js +13 -5
- package/dist/es2019/nodeviews/codeBlockNodeWithToDOMFixed.js +5 -4
- package/dist/es2019/nodeviews/extensions/foldGutter.js +97 -0
- package/dist/es2019/ui/theme.js +30 -0
- package/dist/esm/codeBlockAdvancedPlugin.js +6 -2
- package/dist/esm/nodeviews/codeBlockAdvanced.js +13 -5
- package/dist/esm/nodeviews/codeBlockNodeWithToDOMFixed.js +5 -4
- package/dist/esm/nodeviews/extensions/foldGutter.js +94 -0
- package/dist/esm/ui/theme.js +30 -0
- package/dist/types/codeBlockAdvancedPluginType.d.ts +5 -3
- package/dist/types/index.d.ts +1 -1
- package/dist/types/nodeviews/codeBlockAdvanced.d.ts +2 -1
- package/dist/types/nodeviews/codeBlockNodeWithToDOMFixed.d.ts +5 -1
- package/dist/types/nodeviews/extensions/foldGutter.d.ts +3 -0
- package/dist/types/nodeviews/lazyCodeBlockAdvanced.d.ts +1 -0
- package/dist/types/pm-plugins/main.d.ts +1 -0
- package/dist/types/ui/theme.d.ts +1 -0
- package/dist/types-ts4.5/codeBlockAdvancedPluginType.d.ts +5 -3
- package/dist/types-ts4.5/index.d.ts +1 -1
- package/dist/types-ts4.5/nodeviews/codeBlockAdvanced.d.ts +2 -1
- package/dist/types-ts4.5/nodeviews/codeBlockNodeWithToDOMFixed.d.ts +5 -1
- package/dist/types-ts4.5/nodeviews/extensions/foldGutter.d.ts +3 -0
- package/dist/types-ts4.5/nodeviews/lazyCodeBlockAdvanced.d.ts +1 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +1 -0
- package/dist/types-ts4.5/ui/theme.d.ts +1 -0
- package/package.json +4 -5
- package/src/codeBlockAdvancedPlugin.tsx +7 -2
- package/src/codeBlockAdvancedPluginType.ts +6 -5
- package/src/index.ts +4 -1
- package/src/nodeviews/codeBlockAdvanced.ts +13 -4
- package/src/nodeviews/codeBlockNodeWithToDOMFixed.ts +11 -4
- package/src/nodeviews/extensions/foldGutter.ts +128 -0
- package/src/nodeviews/lazyCodeBlockAdvanced.ts +1 -0
- package/src/pm-plugins/main.ts +1 -0
- package/src/ui/theme.ts +31 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-code-block-advanced
|
|
2
2
|
|
|
3
|
+
## 3.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#199487](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/199487)
|
|
8
|
+
[`9146513a60d45`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/9146513a60d45) -
|
|
9
|
+
Add a new experiment for code folding in the editor.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
|
|
3
15
|
## 3.0.7
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -12,20 +12,24 @@ var codeBlockAdvancedPlugin = exports.codeBlockAdvancedPlugin = function codeBlo
|
|
|
12
12
|
return {
|
|
13
13
|
name: 'codeBlockAdvanced',
|
|
14
14
|
nodes: function nodes() {
|
|
15
|
+
var _config$allowCodeFold;
|
|
15
16
|
return [{
|
|
16
17
|
name: 'codeBlock',
|
|
17
|
-
node: (0, _codeBlockNodeWithToDOMFixed.codeBlockNodeWithFixedToDOM)(
|
|
18
|
+
node: (0, _codeBlockNodeWithToDOMFixed.codeBlockNodeWithFixedToDOM)({
|
|
19
|
+
allowCodeFolding: (_config$allowCodeFold = config === null || config === void 0 ? void 0 : config.allowCodeFolding) !== null && _config$allowCodeFold !== void 0 ? _config$allowCodeFold : false
|
|
20
|
+
})
|
|
18
21
|
}];
|
|
19
22
|
},
|
|
20
23
|
pmPlugins: function pmPlugins() {
|
|
21
24
|
return [{
|
|
22
25
|
name: 'codeBlockAdvancedPlugin',
|
|
23
26
|
plugin: function plugin(_ref2) {
|
|
24
|
-
var _config$extensions;
|
|
27
|
+
var _config$extensions, _config$allowCodeFold2;
|
|
25
28
|
var getIntl = _ref2.getIntl;
|
|
26
29
|
return (0, _main.createPlugin)({
|
|
27
30
|
api: api,
|
|
28
31
|
extensions: (_config$extensions = config === null || config === void 0 ? void 0 : config.extensions) !== null && _config$extensions !== void 0 ? _config$extensions : [],
|
|
32
|
+
allowCodeFolding: (_config$allowCodeFold2 = config === null || config === void 0 ? void 0 : config.allowCodeFolding) !== null && _config$allowCodeFold2 !== void 0 ? _config$allowCodeFold2 : false,
|
|
29
33
|
getIntl: getIntl
|
|
30
34
|
});
|
|
31
35
|
}
|
|
@@ -24,6 +24,7 @@ var _theme = require("../ui/theme");
|
|
|
24
24
|
var _syncCMWithPM = require("./codemirrorSync/syncCMWithPM");
|
|
25
25
|
var _updateCMSelection = require("./codemirrorSync/updateCMSelection");
|
|
26
26
|
var _firstCodeBlockInDocument = require("./extensions/firstCodeBlockInDocument");
|
|
27
|
+
var _foldGutter = require("./extensions/foldGutter");
|
|
27
28
|
var _keymap = require("./extensions/keymap");
|
|
28
29
|
var _manageSelectionMarker = require("./extensions/manageSelectionMarker");
|
|
29
30
|
var _prosemirrorDecorations = require("./extensions/prosemirrorDecorations");
|
|
@@ -67,6 +68,10 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
|
|
|
67
68
|
var _config$getIntl = config.getIntl(),
|
|
68
69
|
formatMessage = _config$getIntl.formatMessage;
|
|
69
70
|
var formattedAriaLabel = formatMessage(_messages.blockTypeMessages.codeblock);
|
|
71
|
+
var selectNode = function selectNode() {
|
|
72
|
+
_this.selectCodeBlockNode(undefined);
|
|
73
|
+
_this.view.focus();
|
|
74
|
+
};
|
|
70
75
|
this.cm = new _view.EditorView({
|
|
71
76
|
doc: this.node.textContent,
|
|
72
77
|
extensions: [].concat((0, _toConsumableArray2.default)(config.extensions), [this.lineWrappingCompartment.of((0, _codeBlock.isCodeBlockWordWrapEnabled)(node) ? _view.EditorView.lineWrapping : []), this.languageCompartment.of([]), this.pmDecorationsCompartment.of(this.pmFacet.compute([], function () {
|
|
@@ -78,11 +83,12 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
|
|
|
78
83
|
selectCodeBlockNode: this.selectCodeBlockNode.bind(this),
|
|
79
84
|
onMaybeNodeSelection: onMaybeNodeSelection,
|
|
80
85
|
customFindReplace: Boolean((_config$api3 = config.api) === null || _config$api3 === void 0 ? void 0 : _config$api3.findReplace)
|
|
81
|
-
}),
|
|
86
|
+
}),
|
|
87
|
+
// Goes before cmTheme to override styles
|
|
88
|
+
config.allowCodeFolding ? [_theme.codeFoldingTheme] : [], _theme.cmTheme, (0, _language.syntaxHighlighting)(_syntaxHighlightingTheme.highlightStyle), (0, _language.bracketMatching)(), (0, _view.lineNumbers)({
|
|
82
89
|
domEventHandlers: {
|
|
83
90
|
click: function click() {
|
|
84
|
-
|
|
85
|
-
_this.view.focus();
|
|
91
|
+
selectNode();
|
|
86
92
|
return true;
|
|
87
93
|
}
|
|
88
94
|
}
|
|
@@ -99,7 +105,9 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
|
|
|
99
105
|
class: 'code-block'
|
|
100
106
|
}), (0, _manageSelectionMarker.manageSelectionMarker)(config.api), (0, _prosemirrorDecorations.prosemirrorDecorationPlugin)(this.pmFacet, view, getPos), (0, _tripleClickExtension.tripleClickSelectAllExtension)(), (0, _firstCodeBlockInDocument.firstCodeBlockInDocument)(getPos), _view.EditorView.contentAttributes.of({
|
|
101
107
|
'aria-label': formattedAriaLabel
|
|
102
|
-
})
|
|
108
|
+
}), config.allowCodeFolding ? [(0, _foldGutter.foldGutterExtension)({
|
|
109
|
+
selectNode: selectNode
|
|
110
|
+
})] : []])
|
|
103
111
|
});
|
|
104
112
|
|
|
105
113
|
// We append an additional element that fixes a selection bug on chrome if the code block
|
|
@@ -21,7 +21,7 @@ var codeBlockClassNames = {
|
|
|
21
21
|
var MATCH_NEWLINES = new RegExp('\n', 'gu');
|
|
22
22
|
|
|
23
23
|
// Based on: `packages/editor/editor-plugin-code-block/src/nodeviews/code-block.ts`
|
|
24
|
-
var _toDOM = function toDOM(node, formattedAriaLabel) {
|
|
24
|
+
var _toDOM = function toDOM(node, formattedAriaLabel, config) {
|
|
25
25
|
var totalLineCount = 1;
|
|
26
26
|
node.forEach(function (node) {
|
|
27
27
|
var text = node.text;
|
|
@@ -49,7 +49,8 @@ var _toDOM = function toDOM(node, formattedAriaLabel) {
|
|
|
49
49
|
backgroundColor: "var(--ds-background-neutral, #091E420F)",
|
|
50
50
|
position: 'relative',
|
|
51
51
|
width: 'var(--lineNumberGutterWidth, 2rem)',
|
|
52
|
-
|
|
52
|
+
/* top and bottom | left and right */
|
|
53
|
+
padding: config.allowCodeFolding ? "var(--ds-space-100, 8px)".concat(" ", "var(--ds-space-250, 20px)", " ", "var(--ds-space-100, 8px)", " ", "var(--ds-space-075, 6px)") : "var(--ds-space-100, 8px)",
|
|
53
54
|
flexShrink: 0,
|
|
54
55
|
fontSize: '0.875rem',
|
|
55
56
|
boxSizing: 'content-box'
|
|
@@ -76,10 +77,10 @@ var _toDOM = function toDOM(node, formattedAriaLabel) {
|
|
|
76
77
|
contenteditable: 'false'
|
|
77
78
|
}]];
|
|
78
79
|
};
|
|
79
|
-
var codeBlockNodeWithFixedToDOM = exports.codeBlockNodeWithFixedToDOM = function codeBlockNodeWithFixedToDOM() {
|
|
80
|
+
var codeBlockNodeWithFixedToDOM = exports.codeBlockNodeWithFixedToDOM = function codeBlockNodeWithFixedToDOM(config) {
|
|
80
81
|
return _objectSpread(_objectSpread({}, _adfSchema.codeBlock), {}, {
|
|
81
82
|
toDOM: function toDOM(node) {
|
|
82
|
-
return _toDOM(node, '');
|
|
83
|
+
return _toDOM(node, '', config);
|
|
83
84
|
}
|
|
84
85
|
});
|
|
85
86
|
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.foldGutterExtension = foldGutterExtension;
|
|
7
|
+
var _language = require("@codemirror/language");
|
|
8
|
+
var _lazyNodeView = require("@atlaskit/editor-common/lazy-node-view");
|
|
9
|
+
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
10
|
+
// Based on platform/packages/design-system/icon/svgs/utility/add.svg
|
|
11
|
+
var chevronDown = ['http://www.w3.org/2000/svg svg', {
|
|
12
|
+
width: '12',
|
|
13
|
+
height: '12',
|
|
14
|
+
fill: 'none',
|
|
15
|
+
viewBox: '0 0 16 16',
|
|
16
|
+
style: 'pointer-events: none;'
|
|
17
|
+
}, ['http://www.w3.org/2000/svg path', {
|
|
18
|
+
fill: 'currentcolor',
|
|
19
|
+
'fill-rule': 'evenodd',
|
|
20
|
+
d: 'm14.53 6.03-6 6a.75.75 0 0 1-1.004.052l-.056-.052-6-6 1.06-1.06L8 10.44l5.47-5.47z',
|
|
21
|
+
'clip-rule': 'evenodd',
|
|
22
|
+
style: 'pointer-events: none;'
|
|
23
|
+
}]];
|
|
24
|
+
var chevronRight = ['http://www.w3.org/2000/svg svg', {
|
|
25
|
+
width: '12',
|
|
26
|
+
height: '12',
|
|
27
|
+
fill: 'none',
|
|
28
|
+
viewBox: '0 0 16 16',
|
|
29
|
+
style: 'pointer-events: none;'
|
|
30
|
+
}, ['http://www.w3.org/2000/svg path', {
|
|
31
|
+
fill: 'currentcolor',
|
|
32
|
+
'fill-rule': 'evenodd',
|
|
33
|
+
d: 'm8.28 1.47 6 6a.75.75 0 0 1 .052 1.004l-.052.056-6 6-1.06-1.06L12.69 8 7.22 2.53z',
|
|
34
|
+
'clip-rule': 'evenodd',
|
|
35
|
+
style: 'pointer-events: none;'
|
|
36
|
+
}]];
|
|
37
|
+
function foldGutterExtension(_ref) {
|
|
38
|
+
var selectNode = _ref.selectNode;
|
|
39
|
+
return [(0, _language.foldGutter)({
|
|
40
|
+
domEventHandlers: {
|
|
41
|
+
click: function click(_view, _, event) {
|
|
42
|
+
// If we're trying to click the button, don't select
|
|
43
|
+
if (event.target instanceof HTMLButtonElement && event.target.getAttribute('data-marker-dom-element')) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
selectNode();
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
markerDOM: function markerDOM(open) {
|
|
51
|
+
var _DOMSerializer$render = _model.DOMSerializer.renderSpec(document, chevronDown),
|
|
52
|
+
downElement = _DOMSerializer$render.dom;
|
|
53
|
+
var _DOMSerializer$render2 = _model.DOMSerializer.renderSpec(document, chevronRight),
|
|
54
|
+
rightElement = _DOMSerializer$render2.dom;
|
|
55
|
+
var htmlElement = document.createElement('button');
|
|
56
|
+
htmlElement.setAttribute('data-marker-dom-element', 'true');
|
|
57
|
+
htmlElement.setAttribute('data-testid', "code-block-fold-button-".concat(open ? 'open' : 'closed'));
|
|
58
|
+
htmlElement.setAttribute('style', (0, _lazyNodeView.convertToInlineCss)({
|
|
59
|
+
background: 'none',
|
|
60
|
+
color: 'inherit',
|
|
61
|
+
border: 'none',
|
|
62
|
+
padding: 0,
|
|
63
|
+
paddingRight: "var(--ds-space-050, 4px)",
|
|
64
|
+
font: 'inherit',
|
|
65
|
+
outline: 'inherit',
|
|
66
|
+
cursor: 'pointer'
|
|
67
|
+
}));
|
|
68
|
+
if (open) {
|
|
69
|
+
if (downElement) {
|
|
70
|
+
htmlElement.appendChild(downElement);
|
|
71
|
+
} else {
|
|
72
|
+
// Fallback - never called
|
|
73
|
+
htmlElement.textContent = '⌄';
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
if (rightElement) {
|
|
77
|
+
htmlElement.appendChild(rightElement);
|
|
78
|
+
} else {
|
|
79
|
+
// Fallback - never called
|
|
80
|
+
htmlElement.textContent = '>';
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return htmlElement;
|
|
84
|
+
}
|
|
85
|
+
}), (0, _language.codeFolding)({
|
|
86
|
+
placeholderDOM: function placeholderDOM(view, onclick, prepared) {
|
|
87
|
+
var htmlElement = document.createElement('button');
|
|
88
|
+
htmlElement.setAttribute('data-marker-dom-element', 'true');
|
|
89
|
+
htmlElement.setAttribute('style', (0, _lazyNodeView.convertToInlineCss)({
|
|
90
|
+
color: 'inherit',
|
|
91
|
+
font: 'inherit',
|
|
92
|
+
cursor: 'pointer'
|
|
93
|
+
}));
|
|
94
|
+
htmlElement.textContent = '…';
|
|
95
|
+
htmlElement.className = 'cm-foldPlaceholder';
|
|
96
|
+
htmlElement.onclick = onclick;
|
|
97
|
+
return htmlElement;
|
|
98
|
+
}
|
|
99
|
+
})];
|
|
100
|
+
}
|
package/dist/cjs/ui/theme.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.cmTheme = void 0;
|
|
6
|
+
exports.codeFoldingTheme = exports.cmTheme = void 0;
|
|
7
7
|
var _view = require("@codemirror/view");
|
|
8
8
|
var lineHeight = '1.5rem';
|
|
9
9
|
var cmTheme = exports.cmTheme = _view.EditorView.theme({
|
|
@@ -74,6 +74,36 @@ var cmTheme = exports.cmTheme = _view.EditorView.theme({
|
|
|
74
74
|
minHeight: lineHeight
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
|
+
var codeFoldingTheme = exports.codeFoldingTheme = _view.EditorView.theme({
|
|
78
|
+
'.cm-gutter': {
|
|
79
|
+
paddingLeft: "var(--ds-space-075, 6px)",
|
|
80
|
+
paddingTop: "var(--ds-space-100, 8px)",
|
|
81
|
+
paddingBottom: "var(--ds-space-100, 8px)",
|
|
82
|
+
paddingRight: "var(--ds-space-0, 0px)"
|
|
83
|
+
},
|
|
84
|
+
'.cm-foldGutter': {
|
|
85
|
+
paddingLeft: "var(--ds-space-050, 4px)"
|
|
86
|
+
},
|
|
87
|
+
'.cm-gutterElement:has([data-marker-dom-element="true"])': {
|
|
88
|
+
color: "var(--ds-icon-subtle, #626F86)"
|
|
89
|
+
},
|
|
90
|
+
'.cm-gutterElement:has([data-marker-dom-element="true"]):hover': {
|
|
91
|
+
color: "var(--ds-text-accent-gray-bolder, #091E42)"
|
|
92
|
+
},
|
|
93
|
+
'.cm-foldPlaceholder': {
|
|
94
|
+
// To give spacing between lines
|
|
95
|
+
height: '20px',
|
|
96
|
+
backgroundColor: "var(--ds-background-accent-gray-subtlest, #F1F2F4)",
|
|
97
|
+
border: 'none',
|
|
98
|
+
color: "var(--ds-text, #172B4D)",
|
|
99
|
+
outline: "1px solid ".concat("var(--ds-border-accent-gray, #758195)"),
|
|
100
|
+
paddingLeft: "var(--ds-space-025, 2px)",
|
|
101
|
+
paddingRight: "var(--ds-space-025, 2px)"
|
|
102
|
+
},
|
|
103
|
+
'.cm-foldPlaceholder:hover': {
|
|
104
|
+
backgroundColor: "var(--ds-background-accent-gray-subtlest-hovered, #DCDFE4)"
|
|
105
|
+
}
|
|
106
|
+
});
|
|
77
107
|
|
|
78
108
|
/**
|
|
79
109
|
* Copied directly from `packages/editor/editor-shared-styles/src/overflow-shadow/overflow-shadow.ts`
|
|
@@ -6,9 +6,12 @@ export const codeBlockAdvancedPlugin = ({
|
|
|
6
6
|
}) => ({
|
|
7
7
|
name: 'codeBlockAdvanced',
|
|
8
8
|
nodes() {
|
|
9
|
+
var _config$allowCodeFold;
|
|
9
10
|
return [{
|
|
10
11
|
name: 'codeBlock',
|
|
11
|
-
node: codeBlockNodeWithFixedToDOM(
|
|
12
|
+
node: codeBlockNodeWithFixedToDOM({
|
|
13
|
+
allowCodeFolding: (_config$allowCodeFold = config === null || config === void 0 ? void 0 : config.allowCodeFolding) !== null && _config$allowCodeFold !== void 0 ? _config$allowCodeFold : false
|
|
14
|
+
})
|
|
12
15
|
}];
|
|
13
16
|
},
|
|
14
17
|
pmPlugins() {
|
|
@@ -17,10 +20,11 @@ export const codeBlockAdvancedPlugin = ({
|
|
|
17
20
|
plugin: ({
|
|
18
21
|
getIntl
|
|
19
22
|
}) => {
|
|
20
|
-
var _config$extensions;
|
|
23
|
+
var _config$extensions, _config$allowCodeFold2;
|
|
21
24
|
return createPlugin({
|
|
22
25
|
api,
|
|
23
26
|
extensions: (_config$extensions = config === null || config === void 0 ? void 0 : config.extensions) !== null && _config$extensions !== void 0 ? _config$extensions : [],
|
|
27
|
+
allowCodeFolding: (_config$allowCodeFold2 = config === null || config === void 0 ? void 0 : config.allowCodeFolding) !== null && _config$allowCodeFold2 !== void 0 ? _config$allowCodeFold2 : false,
|
|
24
28
|
getIntl
|
|
25
29
|
});
|
|
26
30
|
}
|
|
@@ -10,10 +10,11 @@ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
|
10
10
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
11
11
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
12
12
|
import { highlightStyle } from '../ui/syntaxHighlightingTheme';
|
|
13
|
-
import { cmTheme } from '../ui/theme';
|
|
13
|
+
import { cmTheme, codeFoldingTheme } from '../ui/theme';
|
|
14
14
|
import { syncCMWithPM } from './codemirrorSync/syncCMWithPM';
|
|
15
15
|
import { getCMSelectionChanges } from './codemirrorSync/updateCMSelection';
|
|
16
16
|
import { firstCodeBlockInDocument } from './extensions/firstCodeBlockInDocument';
|
|
17
|
+
import { foldGutterExtension } from './extensions/foldGutter';
|
|
17
18
|
import { keymapExtension } from './extensions/keymap';
|
|
18
19
|
import { manageSelectionMarker } from './extensions/manageSelectionMarker';
|
|
19
20
|
import { prosemirrorDecorationPlugin } from './extensions/prosemirrorDecorations';
|
|
@@ -50,6 +51,10 @@ class CodeBlockAdvancedNodeView {
|
|
|
50
51
|
formatMessage
|
|
51
52
|
} = config.getIntl();
|
|
52
53
|
const formattedAriaLabel = formatMessage(blockTypeMessages.codeblock);
|
|
54
|
+
const selectNode = () => {
|
|
55
|
+
this.selectCodeBlockNode(undefined);
|
|
56
|
+
this.view.focus();
|
|
57
|
+
};
|
|
53
58
|
this.cm = new CodeMirror({
|
|
54
59
|
doc: this.node.textContent,
|
|
55
60
|
extensions: [...config.extensions, this.lineWrappingCompartment.of(isCodeBlockWordWrapEnabled(node) ? CodeMirror.lineWrapping : []), this.languageCompartment.of([]), this.pmDecorationsCompartment.of(this.pmFacet.compute([], () => innerDecorations)), keymapExtension({
|
|
@@ -59,11 +64,12 @@ class CodeBlockAdvancedNodeView {
|
|
|
59
64
|
selectCodeBlockNode: this.selectCodeBlockNode.bind(this),
|
|
60
65
|
onMaybeNodeSelection,
|
|
61
66
|
customFindReplace: Boolean((_config$api3 = config.api) === null || _config$api3 === void 0 ? void 0 : _config$api3.findReplace)
|
|
62
|
-
}),
|
|
67
|
+
}),
|
|
68
|
+
// Goes before cmTheme to override styles
|
|
69
|
+
config.allowCodeFolding ? [codeFoldingTheme] : [], cmTheme, syntaxHighlighting(highlightStyle), bracketMatching(), lineNumbers({
|
|
63
70
|
domEventHandlers: {
|
|
64
71
|
click: () => {
|
|
65
|
-
|
|
66
|
-
this.view.focus();
|
|
72
|
+
selectNode();
|
|
67
73
|
return true;
|
|
68
74
|
}
|
|
69
75
|
}
|
|
@@ -78,7 +84,9 @@ class CodeBlockAdvancedNodeView {
|
|
|
78
84
|
class: 'code-block'
|
|
79
85
|
}), manageSelectionMarker(config.api), prosemirrorDecorationPlugin(this.pmFacet, view, getPos), tripleClickSelectAllExtension(), firstCodeBlockInDocument(getPos), CodeMirror.contentAttributes.of({
|
|
80
86
|
'aria-label': formattedAriaLabel
|
|
81
|
-
})
|
|
87
|
+
}), config.allowCodeFolding ? [foldGutterExtension({
|
|
88
|
+
selectNode
|
|
89
|
+
})] : []]
|
|
82
90
|
});
|
|
83
91
|
|
|
84
92
|
// We append an additional element that fixes a selection bug on chrome if the code block
|
|
@@ -11,7 +11,7 @@ const codeBlockClassNames = {
|
|
|
11
11
|
const MATCH_NEWLINES = new RegExp('\n', 'gu');
|
|
12
12
|
|
|
13
13
|
// Based on: `packages/editor/editor-plugin-code-block/src/nodeviews/code-block.ts`
|
|
14
|
-
const toDOM = (node, formattedAriaLabel) => {
|
|
14
|
+
const toDOM = (node, formattedAriaLabel, config) => {
|
|
15
15
|
let totalLineCount = 1;
|
|
16
16
|
node.forEach(node => {
|
|
17
17
|
const text = node.text;
|
|
@@ -37,7 +37,8 @@ const toDOM = (node, formattedAriaLabel) => {
|
|
|
37
37
|
backgroundColor: "var(--ds-background-neutral, #091E420F)",
|
|
38
38
|
position: 'relative',
|
|
39
39
|
width: 'var(--lineNumberGutterWidth, 2rem)',
|
|
40
|
-
|
|
40
|
+
/* top and bottom | left and right */
|
|
41
|
+
padding: config.allowCodeFolding ? `${"var(--ds-space-100, 8px)"} ${"var(--ds-space-250, 20px)"} ${"var(--ds-space-100, 8px)"} ${"var(--ds-space-075, 6px)"}` : "var(--ds-space-100, 8px)",
|
|
41
42
|
flexShrink: 0,
|
|
42
43
|
fontSize: '0.875rem',
|
|
43
44
|
boxSizing: 'content-box'
|
|
@@ -64,9 +65,9 @@ const toDOM = (node, formattedAriaLabel) => {
|
|
|
64
65
|
contenteditable: 'false'
|
|
65
66
|
}]];
|
|
66
67
|
};
|
|
67
|
-
export const codeBlockNodeWithFixedToDOM =
|
|
68
|
+
export const codeBlockNodeWithFixedToDOM = config => {
|
|
68
69
|
return {
|
|
69
70
|
...codeBlock,
|
|
70
|
-
toDOM: node => toDOM(node, '')
|
|
71
|
+
toDOM: node => toDOM(node, '', config)
|
|
71
72
|
};
|
|
72
73
|
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { foldGutter, codeFolding } from '@codemirror/language';
|
|
2
|
+
import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
|
|
3
|
+
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
4
|
+
// Based on platform/packages/design-system/icon/svgs/utility/add.svg
|
|
5
|
+
const chevronDown = ['http://www.w3.org/2000/svg svg', {
|
|
6
|
+
width: '12',
|
|
7
|
+
height: '12',
|
|
8
|
+
fill: 'none',
|
|
9
|
+
viewBox: '0 0 16 16',
|
|
10
|
+
style: 'pointer-events: none;'
|
|
11
|
+
}, ['http://www.w3.org/2000/svg path', {
|
|
12
|
+
fill: 'currentcolor',
|
|
13
|
+
'fill-rule': 'evenodd',
|
|
14
|
+
d: 'm14.53 6.03-6 6a.75.75 0 0 1-1.004.052l-.056-.052-6-6 1.06-1.06L8 10.44l5.47-5.47z',
|
|
15
|
+
'clip-rule': 'evenodd',
|
|
16
|
+
style: 'pointer-events: none;'
|
|
17
|
+
}]];
|
|
18
|
+
const chevronRight = ['http://www.w3.org/2000/svg svg', {
|
|
19
|
+
width: '12',
|
|
20
|
+
height: '12',
|
|
21
|
+
fill: 'none',
|
|
22
|
+
viewBox: '0 0 16 16',
|
|
23
|
+
style: 'pointer-events: none;'
|
|
24
|
+
}, ['http://www.w3.org/2000/svg path', {
|
|
25
|
+
fill: 'currentcolor',
|
|
26
|
+
'fill-rule': 'evenodd',
|
|
27
|
+
d: 'm8.28 1.47 6 6a.75.75 0 0 1 .052 1.004l-.052.056-6 6-1.06-1.06L12.69 8 7.22 2.53z',
|
|
28
|
+
'clip-rule': 'evenodd',
|
|
29
|
+
style: 'pointer-events: none;'
|
|
30
|
+
}]];
|
|
31
|
+
export function foldGutterExtension({
|
|
32
|
+
selectNode
|
|
33
|
+
}) {
|
|
34
|
+
return [foldGutter({
|
|
35
|
+
domEventHandlers: {
|
|
36
|
+
click: (_view, _, event) => {
|
|
37
|
+
// If we're trying to click the button, don't select
|
|
38
|
+
if (event.target instanceof HTMLButtonElement && event.target.getAttribute('data-marker-dom-element')) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
selectNode();
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
markerDOM: open => {
|
|
46
|
+
const {
|
|
47
|
+
dom: downElement
|
|
48
|
+
} = DOMSerializer.renderSpec(document, chevronDown);
|
|
49
|
+
const {
|
|
50
|
+
dom: rightElement
|
|
51
|
+
} = DOMSerializer.renderSpec(document, chevronRight);
|
|
52
|
+
const htmlElement = document.createElement('button');
|
|
53
|
+
htmlElement.setAttribute('data-marker-dom-element', 'true');
|
|
54
|
+
htmlElement.setAttribute('data-testid', `code-block-fold-button-${open ? 'open' : 'closed'}`);
|
|
55
|
+
htmlElement.setAttribute('style', convertToInlineCss({
|
|
56
|
+
background: 'none',
|
|
57
|
+
color: 'inherit',
|
|
58
|
+
border: 'none',
|
|
59
|
+
padding: 0,
|
|
60
|
+
paddingRight: "var(--ds-space-050, 4px)",
|
|
61
|
+
font: 'inherit',
|
|
62
|
+
outline: 'inherit',
|
|
63
|
+
cursor: 'pointer'
|
|
64
|
+
}));
|
|
65
|
+
if (open) {
|
|
66
|
+
if (downElement) {
|
|
67
|
+
htmlElement.appendChild(downElement);
|
|
68
|
+
} else {
|
|
69
|
+
// Fallback - never called
|
|
70
|
+
htmlElement.textContent = '⌄';
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
if (rightElement) {
|
|
74
|
+
htmlElement.appendChild(rightElement);
|
|
75
|
+
} else {
|
|
76
|
+
// Fallback - never called
|
|
77
|
+
htmlElement.textContent = '>';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return htmlElement;
|
|
81
|
+
}
|
|
82
|
+
}), codeFolding({
|
|
83
|
+
placeholderDOM(view, onclick, prepared) {
|
|
84
|
+
const htmlElement = document.createElement('button');
|
|
85
|
+
htmlElement.setAttribute('data-marker-dom-element', 'true');
|
|
86
|
+
htmlElement.setAttribute('style', convertToInlineCss({
|
|
87
|
+
color: 'inherit',
|
|
88
|
+
font: 'inherit',
|
|
89
|
+
cursor: 'pointer'
|
|
90
|
+
}));
|
|
91
|
+
htmlElement.textContent = '…';
|
|
92
|
+
htmlElement.className = 'cm-foldPlaceholder';
|
|
93
|
+
htmlElement.onclick = onclick;
|
|
94
|
+
return htmlElement;
|
|
95
|
+
}
|
|
96
|
+
})];
|
|
97
|
+
}
|
package/dist/es2019/ui/theme.js
CHANGED
|
@@ -68,6 +68,36 @@ export const cmTheme = CodeMirror.theme({
|
|
|
68
68
|
minHeight: lineHeight
|
|
69
69
|
}
|
|
70
70
|
});
|
|
71
|
+
export const codeFoldingTheme = CodeMirror.theme({
|
|
72
|
+
'.cm-gutter': {
|
|
73
|
+
paddingLeft: "var(--ds-space-075, 6px)",
|
|
74
|
+
paddingTop: "var(--ds-space-100, 8px)",
|
|
75
|
+
paddingBottom: "var(--ds-space-100, 8px)",
|
|
76
|
+
paddingRight: "var(--ds-space-0, 0px)"
|
|
77
|
+
},
|
|
78
|
+
'.cm-foldGutter': {
|
|
79
|
+
paddingLeft: "var(--ds-space-050, 4px)"
|
|
80
|
+
},
|
|
81
|
+
'.cm-gutterElement:has([data-marker-dom-element="true"])': {
|
|
82
|
+
color: "var(--ds-icon-subtle, #626F86)"
|
|
83
|
+
},
|
|
84
|
+
'.cm-gutterElement:has([data-marker-dom-element="true"]):hover': {
|
|
85
|
+
color: "var(--ds-text-accent-gray-bolder, #091E42)"
|
|
86
|
+
},
|
|
87
|
+
'.cm-foldPlaceholder': {
|
|
88
|
+
// To give spacing between lines
|
|
89
|
+
height: '20px',
|
|
90
|
+
backgroundColor: "var(--ds-background-accent-gray-subtlest, #F1F2F4)",
|
|
91
|
+
border: 'none',
|
|
92
|
+
color: "var(--ds-text, #172B4D)",
|
|
93
|
+
outline: `1px solid ${"var(--ds-border-accent-gray, #758195)"}`,
|
|
94
|
+
paddingLeft: "var(--ds-space-025, 2px)",
|
|
95
|
+
paddingRight: "var(--ds-space-025, 2px)"
|
|
96
|
+
},
|
|
97
|
+
'.cm-foldPlaceholder:hover': {
|
|
98
|
+
backgroundColor: "var(--ds-background-accent-gray-subtlest-hovered, #DCDFE4)"
|
|
99
|
+
}
|
|
100
|
+
});
|
|
71
101
|
|
|
72
102
|
/**
|
|
73
103
|
* Copied directly from `packages/editor/editor-shared-styles/src/overflow-shadow/overflow-shadow.ts`
|
|
@@ -6,20 +6,24 @@ export var codeBlockAdvancedPlugin = function codeBlockAdvancedPlugin(_ref) {
|
|
|
6
6
|
return {
|
|
7
7
|
name: 'codeBlockAdvanced',
|
|
8
8
|
nodes: function nodes() {
|
|
9
|
+
var _config$allowCodeFold;
|
|
9
10
|
return [{
|
|
10
11
|
name: 'codeBlock',
|
|
11
|
-
node: codeBlockNodeWithFixedToDOM(
|
|
12
|
+
node: codeBlockNodeWithFixedToDOM({
|
|
13
|
+
allowCodeFolding: (_config$allowCodeFold = config === null || config === void 0 ? void 0 : config.allowCodeFolding) !== null && _config$allowCodeFold !== void 0 ? _config$allowCodeFold : false
|
|
14
|
+
})
|
|
12
15
|
}];
|
|
13
16
|
},
|
|
14
17
|
pmPlugins: function pmPlugins() {
|
|
15
18
|
return [{
|
|
16
19
|
name: 'codeBlockAdvancedPlugin',
|
|
17
20
|
plugin: function plugin(_ref2) {
|
|
18
|
-
var _config$extensions;
|
|
21
|
+
var _config$extensions, _config$allowCodeFold2;
|
|
19
22
|
var getIntl = _ref2.getIntl;
|
|
20
23
|
return createPlugin({
|
|
21
24
|
api: api,
|
|
22
25
|
extensions: (_config$extensions = config === null || config === void 0 ? void 0 : config.extensions) !== null && _config$extensions !== void 0 ? _config$extensions : [],
|
|
26
|
+
allowCodeFolding: (_config$allowCodeFold2 = config === null || config === void 0 ? void 0 : config.allowCodeFolding) !== null && _config$allowCodeFold2 !== void 0 ? _config$allowCodeFold2 : false,
|
|
23
27
|
getIntl: getIntl
|
|
24
28
|
});
|
|
25
29
|
}
|
|
@@ -13,10 +13,11 @@ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
|
13
13
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
14
14
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
15
15
|
import { highlightStyle } from '../ui/syntaxHighlightingTheme';
|
|
16
|
-
import { cmTheme } from '../ui/theme';
|
|
16
|
+
import { cmTheme, codeFoldingTheme } from '../ui/theme';
|
|
17
17
|
import { syncCMWithPM } from './codemirrorSync/syncCMWithPM';
|
|
18
18
|
import { getCMSelectionChanges } from './codemirrorSync/updateCMSelection';
|
|
19
19
|
import { firstCodeBlockInDocument } from './extensions/firstCodeBlockInDocument';
|
|
20
|
+
import { foldGutterExtension } from './extensions/foldGutter';
|
|
20
21
|
import { keymapExtension } from './extensions/keymap';
|
|
21
22
|
import { manageSelectionMarker } from './extensions/manageSelectionMarker';
|
|
22
23
|
import { prosemirrorDecorationPlugin } from './extensions/prosemirrorDecorations';
|
|
@@ -60,6 +61,10 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
|
|
|
60
61
|
var _config$getIntl = config.getIntl(),
|
|
61
62
|
formatMessage = _config$getIntl.formatMessage;
|
|
62
63
|
var formattedAriaLabel = formatMessage(blockTypeMessages.codeblock);
|
|
64
|
+
var selectNode = function selectNode() {
|
|
65
|
+
_this.selectCodeBlockNode(undefined);
|
|
66
|
+
_this.view.focus();
|
|
67
|
+
};
|
|
63
68
|
this.cm = new CodeMirror({
|
|
64
69
|
doc: this.node.textContent,
|
|
65
70
|
extensions: [].concat(_toConsumableArray(config.extensions), [this.lineWrappingCompartment.of(isCodeBlockWordWrapEnabled(node) ? CodeMirror.lineWrapping : []), this.languageCompartment.of([]), this.pmDecorationsCompartment.of(this.pmFacet.compute([], function () {
|
|
@@ -71,11 +76,12 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
|
|
|
71
76
|
selectCodeBlockNode: this.selectCodeBlockNode.bind(this),
|
|
72
77
|
onMaybeNodeSelection: onMaybeNodeSelection,
|
|
73
78
|
customFindReplace: Boolean((_config$api3 = config.api) === null || _config$api3 === void 0 ? void 0 : _config$api3.findReplace)
|
|
74
|
-
}),
|
|
79
|
+
}),
|
|
80
|
+
// Goes before cmTheme to override styles
|
|
81
|
+
config.allowCodeFolding ? [codeFoldingTheme] : [], cmTheme, syntaxHighlighting(highlightStyle), bracketMatching(), lineNumbers({
|
|
75
82
|
domEventHandlers: {
|
|
76
83
|
click: function click() {
|
|
77
|
-
|
|
78
|
-
_this.view.focus();
|
|
84
|
+
selectNode();
|
|
79
85
|
return true;
|
|
80
86
|
}
|
|
81
87
|
}
|
|
@@ -92,7 +98,9 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
|
|
|
92
98
|
class: 'code-block'
|
|
93
99
|
}), manageSelectionMarker(config.api), prosemirrorDecorationPlugin(this.pmFacet, view, getPos), tripleClickSelectAllExtension(), firstCodeBlockInDocument(getPos), CodeMirror.contentAttributes.of({
|
|
94
100
|
'aria-label': formattedAriaLabel
|
|
95
|
-
})
|
|
101
|
+
}), config.allowCodeFolding ? [foldGutterExtension({
|
|
102
|
+
selectNode: selectNode
|
|
103
|
+
})] : []])
|
|
96
104
|
});
|
|
97
105
|
|
|
98
106
|
// We append an additional element that fixes a selection bug on chrome if the code block
|
|
@@ -14,7 +14,7 @@ var codeBlockClassNames = {
|
|
|
14
14
|
var MATCH_NEWLINES = new RegExp('\n', 'gu');
|
|
15
15
|
|
|
16
16
|
// Based on: `packages/editor/editor-plugin-code-block/src/nodeviews/code-block.ts`
|
|
17
|
-
var _toDOM = function toDOM(node, formattedAriaLabel) {
|
|
17
|
+
var _toDOM = function toDOM(node, formattedAriaLabel, config) {
|
|
18
18
|
var totalLineCount = 1;
|
|
19
19
|
node.forEach(function (node) {
|
|
20
20
|
var text = node.text;
|
|
@@ -42,7 +42,8 @@ var _toDOM = function toDOM(node, formattedAriaLabel) {
|
|
|
42
42
|
backgroundColor: "var(--ds-background-neutral, #091E420F)",
|
|
43
43
|
position: 'relative',
|
|
44
44
|
width: 'var(--lineNumberGutterWidth, 2rem)',
|
|
45
|
-
|
|
45
|
+
/* top and bottom | left and right */
|
|
46
|
+
padding: config.allowCodeFolding ? "var(--ds-space-100, 8px)".concat(" ", "var(--ds-space-250, 20px)", " ", "var(--ds-space-100, 8px)", " ", "var(--ds-space-075, 6px)") : "var(--ds-space-100, 8px)",
|
|
46
47
|
flexShrink: 0,
|
|
47
48
|
fontSize: '0.875rem',
|
|
48
49
|
boxSizing: 'content-box'
|
|
@@ -69,10 +70,10 @@ var _toDOM = function toDOM(node, formattedAriaLabel) {
|
|
|
69
70
|
contenteditable: 'false'
|
|
70
71
|
}]];
|
|
71
72
|
};
|
|
72
|
-
export var codeBlockNodeWithFixedToDOM = function codeBlockNodeWithFixedToDOM() {
|
|
73
|
+
export var codeBlockNodeWithFixedToDOM = function codeBlockNodeWithFixedToDOM(config) {
|
|
73
74
|
return _objectSpread(_objectSpread({}, codeBlock), {}, {
|
|
74
75
|
toDOM: function toDOM(node) {
|
|
75
|
-
return _toDOM(node, '');
|
|
76
|
+
return _toDOM(node, '', config);
|
|
76
77
|
}
|
|
77
78
|
});
|
|
78
79
|
};
|