@atlaskit/code 14.4.8 → 14.5.1
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 +25 -0
- package/dist/cjs/bidi-warning/bidi-warning-decorator.js +8 -0
- package/dist/cjs/bidi-warning/ui/index.js +8 -0
- package/dist/cjs/code-block.js +22 -20
- package/dist/cjs/internal/theme/styles.js +20 -9
- package/dist/cjs/syntax-highlighter/async.js +88 -0
- package/dist/cjs/syntax-highlighter/index.js +44 -0
- package/dist/cjs/syntax-highlighter/lib/highlight.js +91 -0
- package/dist/cjs/syntax-highlighter/lib/process/create-line-element.js +74 -0
- package/dist/cjs/syntax-highlighter/lib/process/create-line.js +32 -0
- package/dist/cjs/syntax-highlighter/lib/process/flatten-code-tree.js +29 -0
- package/dist/cjs/syntax-highlighter/lib/process/get-code-tree.js +22 -0
- package/dist/cjs/syntax-highlighter/lib/process/get-inline-line-number.js +23 -0
- package/dist/cjs/syntax-highlighter/lib/process/index.js +122 -0
- package/dist/cjs/syntax-highlighter/lib/react-renderer/create-children.js +21 -0
- package/dist/cjs/syntax-highlighter/lib/react-renderer/create-element.js +57 -0
- package/dist/cjs/syntax-highlighter/lib/react-renderer/index.js +30 -0
- package/dist/cjs/syntax-highlighter/types.js +31 -0
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/bidi-warning/bidi-warning-decorator.js +8 -0
- package/dist/es2019/bidi-warning/ui/index.js +8 -0
- package/dist/es2019/code-block.js +18 -18
- package/dist/es2019/internal/theme/styles.js +20 -9
- package/dist/es2019/syntax-highlighter/async.js +51 -0
- package/dist/es2019/syntax-highlighter/index.js +38 -0
- package/dist/es2019/syntax-highlighter/lib/highlight.js +73 -0
- package/dist/es2019/syntax-highlighter/lib/process/create-line-element.js +65 -0
- package/dist/es2019/syntax-highlighter/lib/process/create-line.js +23 -0
- package/dist/es2019/syntax-highlighter/lib/process/flatten-code-tree.js +18 -0
- package/dist/es2019/syntax-highlighter/lib/process/get-code-tree.js +16 -0
- package/dist/es2019/syntax-highlighter/lib/process/get-inline-line-number.js +17 -0
- package/dist/es2019/syntax-highlighter/lib/process/index.js +114 -0
- package/dist/es2019/syntax-highlighter/lib/react-renderer/create-children.js +12 -0
- package/dist/es2019/syntax-highlighter/lib/react-renderer/create-element.js +53 -0
- package/dist/es2019/syntax-highlighter/lib/react-renderer/index.js +23 -0
- package/dist/es2019/syntax-highlighter/types.js +9 -0
- package/dist/es2019/version.json +1 -1
- package/dist/esm/bidi-warning/bidi-warning-decorator.js +8 -0
- package/dist/esm/bidi-warning/ui/index.js +8 -0
- package/dist/esm/code-block.js +20 -19
- package/dist/esm/internal/theme/styles.js +20 -9
- package/dist/esm/syntax-highlighter/async.js +76 -0
- package/dist/esm/syntax-highlighter/index.js +38 -0
- package/dist/esm/syntax-highlighter/lib/highlight.js +84 -0
- package/dist/esm/syntax-highlighter/lib/process/create-line-element.js +67 -0
- package/dist/esm/syntax-highlighter/lib/process/create-line.js +24 -0
- package/dist/esm/syntax-highlighter/lib/process/flatten-code-tree.js +22 -0
- package/dist/esm/syntax-highlighter/lib/process/get-code-tree.js +16 -0
- package/dist/esm/syntax-highlighter/lib/process/get-inline-line-number.js +17 -0
- package/dist/esm/syntax-highlighter/lib/process/index.js +115 -0
- package/dist/esm/syntax-highlighter/lib/react-renderer/create-children.js +14 -0
- package/dist/esm/syntax-highlighter/lib/react-renderer/create-element.js +50 -0
- package/dist/esm/syntax-highlighter/lib/react-renderer/index.js +24 -0
- package/dist/esm/syntax-highlighter/types.js +24 -0
- package/dist/esm/version.json +1 -1
- package/dist/types/bidi-warning/bidi-warning-decorator.d.ts +7 -0
- package/dist/types/bidi-warning/ui/index.d.ts +8 -0
- package/dist/types/bidi-warning/ui/types.d.ts +11 -15
- package/dist/types/extract-react-types/code-block.d.ts +24 -14
- package/dist/types/internal/theme/styles.d.ts +1 -1
- package/dist/types/internal/types.d.ts +31 -18
- package/dist/types/syntax-highlighter/async.d.ts +3 -0
- package/dist/types/syntax-highlighter/index.d.ts +36 -0
- package/dist/types/syntax-highlighter/lib/highlight.d.ts +12 -0
- package/dist/types/syntax-highlighter/lib/process/create-line-element.d.ts +9 -0
- package/dist/types/syntax-highlighter/lib/process/create-line.d.ts +3 -0
- package/dist/types/syntax-highlighter/lib/process/flatten-code-tree.d.ts +2 -0
- package/dist/types/syntax-highlighter/lib/process/get-code-tree.d.ts +2 -0
- package/dist/types/syntax-highlighter/lib/process/get-inline-line-number.d.ts +2 -0
- package/dist/types/syntax-highlighter/lib/process/index.d.ts +17 -0
- package/dist/types/syntax-highlighter/lib/react-renderer/create-children.d.ts +3 -0
- package/dist/types/syntax-highlighter/lib/react-renderer/create-element.d.ts +7 -0
- package/dist/types/syntax-highlighter/lib/react-renderer/index.d.ts +15 -0
- package/dist/types/syntax-highlighter/types.d.ts +129 -0
- package/dist/types/types.d.ts +10 -11
- package/package.json +14 -10
- package/report.api.md +1 -0
- package/dist/cjs/react-syntax-highlighter-bidi-warning-renderer.js +0 -156
- package/dist/es2019/react-syntax-highlighter-bidi-warning-renderer.js +0 -149
- package/dist/esm/react-syntax-highlighter-bidi-warning-renderer.js +0 -155
- package/dist/types/react-syntax-highlighter-bidi-warning-renderer.d.ts +0 -9
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import getInlineLineNumber from './get-inline-line-number';
|
|
2
|
+
export default function createLineElement({
|
|
3
|
+
children,
|
|
4
|
+
lineNumber,
|
|
5
|
+
showLineNumbers,
|
|
6
|
+
lineProps = {},
|
|
7
|
+
className = []
|
|
8
|
+
}) {
|
|
9
|
+
const properties = typeof lineProps === 'function' ? lineProps(lineNumber) : lineProps;
|
|
10
|
+
properties.className = className;
|
|
11
|
+
let currentChildren = children;
|
|
12
|
+
if (lineNumber && showLineNumbers) {
|
|
13
|
+
// When syntax highlighting is NOT turned on, the entire LOC is just a single
|
|
14
|
+
// child. We can then happily create the line number and the LOC as siblings...
|
|
15
|
+
if (currentChildren.length === 1) {
|
|
16
|
+
currentChildren = [getInlineLineNumber(lineNumber), ...currentChildren];
|
|
17
|
+
} else {
|
|
18
|
+
// ... However, when syntax highlighting IS on, a span is created for each
|
|
19
|
+
// tokenised node in the AST (eg. <span>import</span><span>React</span>).
|
|
20
|
+
// When shouldWrapLongLines is true, the row becomes `display: flex` and
|
|
21
|
+
// forces all its children to be equal height. This can be a source of
|
|
22
|
+
// visual bugs where a LOC is broken up weirdly into segments.
|
|
23
|
+
//
|
|
24
|
+
// +---------------------------------------+
|
|
25
|
+
// | row |
|
|
26
|
+
// | +----+ +-------+ +--------+ +------+ |
|
|
27
|
+
// | |line| |key | |keywords| |key | |
|
|
28
|
+
// | |no. | |word | | | |word | |
|
|
29
|
+
// | | | | | | | | | |
|
|
30
|
+
// | +----+ +-------+ +--------+ +------+ |
|
|
31
|
+
// +---------------------------------------+
|
|
32
|
+
//
|
|
33
|
+
// Nesting the children one layer deeper (i.e. creating an extra span)
|
|
34
|
+
// ensures that the line number and the ENTIRE line of code are aligned by
|
|
35
|
+
// the parent flexbox (the row).
|
|
36
|
+
//
|
|
37
|
+
// +---------------------------------------------+
|
|
38
|
+
// | row |
|
|
39
|
+
// | +----+ +--------------------------------+ |
|
|
40
|
+
// | |line| | extra span we are creating | |
|
|
41
|
+
// | |no. | | +-------+ +--------+ +------+ | |
|
|
42
|
+
// | | | | |key | |keywords| |key | | |
|
|
43
|
+
// | | | | |word | | | |word | | |
|
|
44
|
+
// | | | | | | | | | | | |
|
|
45
|
+
// | | | | +-------+ +--------+ +------+ | |
|
|
46
|
+
// | +----+ +--------------------------------+ |
|
|
47
|
+
// +---------------------------------------------+
|
|
48
|
+
//
|
|
49
|
+
currentChildren = [getInlineLineNumber(lineNumber), {
|
|
50
|
+
type: 'element',
|
|
51
|
+
tagName: 'span',
|
|
52
|
+
properties: {
|
|
53
|
+
className: []
|
|
54
|
+
},
|
|
55
|
+
children: currentChildren
|
|
56
|
+
}];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
type: 'element',
|
|
61
|
+
tagName: 'span',
|
|
62
|
+
properties,
|
|
63
|
+
children: currentChildren
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import createLineElement from './create-line-element';
|
|
2
|
+
import getInlineLineNumber from './get-inline-line-number';
|
|
3
|
+
function createLineGenerator(lineProps, shouldCreateParentElementForLines, showLineNumbers) {
|
|
4
|
+
return (children, lineNumber, className = []) => {
|
|
5
|
+
// Needed for more complex line creation
|
|
6
|
+
if (shouldCreateParentElementForLines || className.length > 0) {
|
|
7
|
+
return createLineElement({
|
|
8
|
+
children,
|
|
9
|
+
lineNumber,
|
|
10
|
+
showLineNumbers,
|
|
11
|
+
lineProps,
|
|
12
|
+
className
|
|
13
|
+
});
|
|
14
|
+
} else {
|
|
15
|
+
// Simple line creation without the bells and whistles
|
|
16
|
+
if (showLineNumbers && lineNumber) {
|
|
17
|
+
children.unshift(getInlineLineNumber(lineNumber));
|
|
18
|
+
}
|
|
19
|
+
return children;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export default createLineGenerator;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import createLineElement from './create-line-element';
|
|
2
|
+
export default function flattenCodeTree(tree, offset = 0, className = []) {
|
|
3
|
+
let newTree = [];
|
|
4
|
+
for (let i = 0; i < tree.length; i++) {
|
|
5
|
+
const node = tree[i];
|
|
6
|
+
if (node.type === 'text') {
|
|
7
|
+
newTree.push(createLineElement({
|
|
8
|
+
children: [node],
|
|
9
|
+
lineNumber: offset,
|
|
10
|
+
className
|
|
11
|
+
}));
|
|
12
|
+
} else if (node.children) {
|
|
13
|
+
const classNames = className.concat(node.properties.className || []);
|
|
14
|
+
flattenCodeTree(node.children, offset + 1, classNames).forEach(i => newTree.push(i));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return newTree;
|
|
18
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export default function getCodeTree(language, code, astGenerator) {
|
|
2
|
+
if (language === 'text' || !astGenerator) {
|
|
3
|
+
return [{
|
|
4
|
+
type: 'text',
|
|
5
|
+
value: code
|
|
6
|
+
}];
|
|
7
|
+
}
|
|
8
|
+
try {
|
|
9
|
+
return astGenerator.highlight(code, language);
|
|
10
|
+
} catch (e) {
|
|
11
|
+
return [{
|
|
12
|
+
type: 'text',
|
|
13
|
+
value: code
|
|
14
|
+
}];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export default function getInlineLineNumber(lineNumber) {
|
|
2
|
+
return {
|
|
3
|
+
type: 'element',
|
|
4
|
+
tagName: 'span',
|
|
5
|
+
properties: {
|
|
6
|
+
key: `line-number--${lineNumber}`,
|
|
7
|
+
className: ['comment', 'linenumber', 'ds-line-number'],
|
|
8
|
+
// We're placing the lineNumber in a data-attr on an empty span (hence the
|
|
9
|
+
// empty children array below). This allows CodeBlock to use CSS to
|
|
10
|
+
// generate the content in a pseudo-element, which is a fix for a bug
|
|
11
|
+
// where line numbers were being copied (CSS content can't be copied)
|
|
12
|
+
// https://product-fabric.atlassian.net/browse/DSP-2729
|
|
13
|
+
'data-ds--line-number': lineNumber
|
|
14
|
+
},
|
|
15
|
+
children: []
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import createLineGenerator from './create-line';
|
|
2
|
+
import createLineElement from './create-line-element';
|
|
3
|
+
import flattenCodeTree from './flatten-code-tree';
|
|
4
|
+
import getCodeTree from './get-code-tree';
|
|
5
|
+
const newLineRegex = /\n/g;
|
|
6
|
+
function getNewLines(str) {
|
|
7
|
+
return str.match(newLineRegex);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* __Line Processor__
|
|
11
|
+
*
|
|
12
|
+
* A line processor, that uses refractor to turn code into a tree structure
|
|
13
|
+
* with highlighting metadata and collapses this tree into lines for a renderer.
|
|
14
|
+
*/
|
|
15
|
+
export default function processLines({
|
|
16
|
+
astGenerator,
|
|
17
|
+
code,
|
|
18
|
+
language,
|
|
19
|
+
shouldCreateParentElementForLines,
|
|
20
|
+
lineProps,
|
|
21
|
+
showLineNumbers
|
|
22
|
+
}) {
|
|
23
|
+
const codeTree = getCodeTree(language, code, astGenerator);
|
|
24
|
+
const startingLineNumber = 1;
|
|
25
|
+
const createLine = createLineGenerator(lineProps, shouldCreateParentElementForLines, showLineNumbers);
|
|
26
|
+
const newTree = [];
|
|
27
|
+
let lastLineBreakIndex = -1;
|
|
28
|
+
let index = 0;
|
|
29
|
+
|
|
30
|
+
// Seems odd we flatten the tree immediately - what work could we do on it more performantly than on the lines?
|
|
31
|
+
const tree = flattenCodeTree(codeTree);
|
|
32
|
+
while (index < tree.length) {
|
|
33
|
+
const testNode = tree[index];
|
|
34
|
+
if (testNode.type === 'text') {
|
|
35
|
+
index++;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const node = testNode;
|
|
39
|
+
const firstChildNode = node.children[0];
|
|
40
|
+
if (firstChildNode.type === 'text') {
|
|
41
|
+
const {
|
|
42
|
+
value
|
|
43
|
+
} = firstChildNode;
|
|
44
|
+
const newLines = getNewLines(value);
|
|
45
|
+
if (newLines) {
|
|
46
|
+
const splitValue = value.split('\n');
|
|
47
|
+
splitValue.forEach((text, i) => {
|
|
48
|
+
const lineNumber = newTree.length + startingLineNumber;
|
|
49
|
+
const newChild = {
|
|
50
|
+
type: 'text',
|
|
51
|
+
value: `${text}\n`
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// if it's the first line
|
|
55
|
+
if (i === 0) {
|
|
56
|
+
const children = tree.slice(lastLineBreakIndex + 1, index).concat(createLineElement({
|
|
57
|
+
children: [newChild],
|
|
58
|
+
className: node.properties.className,
|
|
59
|
+
lineNumber
|
|
60
|
+
}));
|
|
61
|
+
const line = createLine(children, lineNumber);
|
|
62
|
+
newTree.push(line);
|
|
63
|
+
|
|
64
|
+
// if it's the last line
|
|
65
|
+
} else if (i === splitValue.length - 1) {
|
|
66
|
+
const nextNode = tree[index + 1];
|
|
67
|
+
const stringChild = nextNode && nextNode.children && nextNode.children[0];
|
|
68
|
+
// Similar to newChild above, but no newline
|
|
69
|
+
const lastLineInPreviousSpan = {
|
|
70
|
+
type: 'text',
|
|
71
|
+
value: `${text}`
|
|
72
|
+
};
|
|
73
|
+
if (stringChild) {
|
|
74
|
+
const newElem = createLineElement({
|
|
75
|
+
children: [lastLineInPreviousSpan],
|
|
76
|
+
className: node.properties.className,
|
|
77
|
+
lineNumber
|
|
78
|
+
});
|
|
79
|
+
tree.splice(index + 1, 0, newElem);
|
|
80
|
+
} else {
|
|
81
|
+
const children = [lastLineInPreviousSpan];
|
|
82
|
+
const line = createLine(children, lineNumber, node.properties.className);
|
|
83
|
+
newTree.push(line);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// if it's neither the first nor the last line
|
|
87
|
+
} else {
|
|
88
|
+
const children = [newChild];
|
|
89
|
+
const line = createLine(children, lineNumber, node.properties.className);
|
|
90
|
+
newTree.push(line);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
lastLineBreakIndex = index;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
index++;
|
|
97
|
+
}
|
|
98
|
+
if (lastLineBreakIndex !== tree.length - 1) {
|
|
99
|
+
const children = tree.slice(lastLineBreakIndex + 1, tree.length);
|
|
100
|
+
if (children && children.length) {
|
|
101
|
+
const lineNumber = newTree.length + startingLineNumber;
|
|
102
|
+
const line = createLine(children, lineNumber);
|
|
103
|
+
newTree.push(line);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (shouldCreateParentElementForLines) {
|
|
107
|
+
return newTree;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// If shouldCreateParentElementForLines was off, we still have a tree structure we need to flatten
|
|
111
|
+
// We have (RefractorNode | RefractorNode[])[] but need RefractorNode[]
|
|
112
|
+
// This seems like a code smell to review
|
|
113
|
+
return newTree.flat(1);
|
|
114
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import createElement from './create-element';
|
|
2
|
+
export default function createChildren(codeBidiWarningConfig) {
|
|
3
|
+
let childrenCount = 0;
|
|
4
|
+
return children => {
|
|
5
|
+
childrenCount += 1;
|
|
6
|
+
return children.map((child, i) => createElement({
|
|
7
|
+
node: child,
|
|
8
|
+
codeBidiWarningConfig,
|
|
9
|
+
key: `code-segment-${childrenCount}-${i}`
|
|
10
|
+
}));
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import CodeBidiWarning from '../../../bidi-warning';
|
|
3
|
+
import codeBidiWarningDecorator from '../../../bidi-warning/bidi-warning-decorator';
|
|
4
|
+
import createChildren from './create-children';
|
|
5
|
+
function createClassNameString(classNames) {
|
|
6
|
+
return classNames ? classNames.join(' ') : '';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// NOTE: This is a function call rather than a React component because, for
|
|
10
|
+
// unknown reasons, it appears to be more performant. We tried and measured both
|
|
11
|
+
// and this stacks up better than as a memoised React component. Something to look
|
|
12
|
+
// into in the future.
|
|
13
|
+
export default function createElement({
|
|
14
|
+
node,
|
|
15
|
+
codeBidiWarningConfig,
|
|
16
|
+
key
|
|
17
|
+
}) {
|
|
18
|
+
if (node.type === 'text') {
|
|
19
|
+
const {
|
|
20
|
+
value
|
|
21
|
+
} = node;
|
|
22
|
+
// occasionally a numeric value is passed when the type is text
|
|
23
|
+
const textValue = `${value}`;
|
|
24
|
+
if (codeBidiWarningConfig.codeBidiWarnings) {
|
|
25
|
+
const decorated = codeBidiWarningDecorator(textValue, ({
|
|
26
|
+
bidiCharacter,
|
|
27
|
+
index
|
|
28
|
+
}) => /*#__PURE__*/React.createElement(CodeBidiWarning, {
|
|
29
|
+
bidiCharacter: bidiCharacter,
|
|
30
|
+
key: index,
|
|
31
|
+
label: codeBidiWarningConfig.codeBidiWarningLabel,
|
|
32
|
+
tooltipEnabled: codeBidiWarningConfig.codeBidiWarningTooltipEnabled
|
|
33
|
+
}));
|
|
34
|
+
return decorated;
|
|
35
|
+
}
|
|
36
|
+
return textValue;
|
|
37
|
+
} else {
|
|
38
|
+
const {
|
|
39
|
+
properties,
|
|
40
|
+
tagName
|
|
41
|
+
} = node;
|
|
42
|
+
const childrenCreator = createChildren(codeBidiWarningConfig);
|
|
43
|
+
const props = {
|
|
44
|
+
...properties,
|
|
45
|
+
className: createClassNameString(properties.className)
|
|
46
|
+
};
|
|
47
|
+
const children = childrenCreator(node.children);
|
|
48
|
+
return /*#__PURE__*/React.createElement(tagName, {
|
|
49
|
+
key,
|
|
50
|
+
...props
|
|
51
|
+
}, children);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import createElement from './create-element';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* __React Renderer__
|
|
6
|
+
*
|
|
7
|
+
* A component that receives processed code lines and renders them into the code
|
|
8
|
+
* rows inside the wrapping span and nested code tag, applying passed props and
|
|
9
|
+
* code bidi warning config settings.
|
|
10
|
+
*/
|
|
11
|
+
export default function ReactRenderer({
|
|
12
|
+
containerProps,
|
|
13
|
+
codeTagProps,
|
|
14
|
+
rows,
|
|
15
|
+
codeBidiWarningConfig
|
|
16
|
+
}) {
|
|
17
|
+
const renderedRows = rows.map((node, i) => createElement({
|
|
18
|
+
node,
|
|
19
|
+
codeBidiWarningConfig,
|
|
20
|
+
key: `code-segment${i}`
|
|
21
|
+
}));
|
|
22
|
+
return /*#__PURE__*/React.createElement("span", containerProps, /*#__PURE__*/React.createElement("code", codeTagProps, renderedRows));
|
|
23
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
// This wrapper supports the async loading of refractor and language grammars. The internal Highlight is a memo() functional component as expected
|
|
3
|
+
// eslint-disable-next-line @repo/internal/react/no-class-components
|
|
4
|
+
export class SyntaxHighlighter extends React.PureComponent {}
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Function that receives current line number as argument and returns a
|
|
8
|
+
* line props object to be applied to each `span` wrapping code line.
|
|
9
|
+
*/
|
package/dist/es2019/version.json
CHANGED
|
@@ -3,6 +3,14 @@ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol
|
|
|
3
3
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
4
4
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
5
5
|
export var bidiCharacterRegex = /[\u202A-\u202E\u2066-\u2069]/g;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* __Code Bidi Warning Decorator__
|
|
9
|
+
*
|
|
10
|
+
* Checks the code to see if it contains any bidi characters.
|
|
11
|
+
* In case if bidi characters found - returns children with decorated
|
|
12
|
+
* bidi characters. If no bidi characters found - original text returned.
|
|
13
|
+
*/
|
|
6
14
|
export default function codeBidiWarningDecorator(originalText, decorate) {
|
|
7
15
|
var matches = _toConsumableArray(originalText.matchAll(bidiCharacterRegex));
|
|
8
16
|
if (matches.length === 0) {
|
|
@@ -4,6 +4,14 @@ var _excluded = ["children"];
|
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import Tooltip from '@atlaskit/tooltip';
|
|
6
6
|
import { Decorator } from './styled';
|
|
7
|
+
/**
|
|
8
|
+
* __Bidi Warning__
|
|
9
|
+
*
|
|
10
|
+
* A component used to render a bidi character warning.
|
|
11
|
+
* A bidi character can be used to perform a "bidi override attack".
|
|
12
|
+
*
|
|
13
|
+
* See https://hello.atlassian.net/wiki/spaces/PRODSEC/pages/1347434677/PSHELP-2943+Investigate+Trojan+Source+Attack+Vulnerability#1)-Providing-visual-cues-for-our-Customers-in-our-affected-products
|
|
14
|
+
*/
|
|
7
15
|
export default function BidiWarning(_ref) {
|
|
8
16
|
var testId = _ref.testId,
|
|
9
17
|
bidiCharacter = _ref.bidiCharacter,
|
package/dist/esm/code-block.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/** @jsx jsx */
|
|
2
2
|
import { memo, useCallback, useMemo } from 'react';
|
|
3
3
|
import { css, jsx } from '@emotion/react';
|
|
4
|
-
import { PrismAsync as SyntaxHighlighter } from 'react-syntax-highlighter';
|
|
5
4
|
import { useGlobalTheme } from '@atlaskit/theme/components';
|
|
6
5
|
import { useHighlightLines } from './internal/hooks/use-highlight';
|
|
7
6
|
import { getCodeBlockStyles, getCodeBlockTheme } from './internal/theme/styles';
|
|
8
7
|
import { normalizeLanguage } from './internal/utils/get-normalized-language';
|
|
9
|
-
import
|
|
8
|
+
import SyntaxHighlighter from './syntax-highlighter';
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* __Code block__
|
|
@@ -34,7 +33,9 @@ var CodeBlock = /*#__PURE__*/memo(function CodeBlock(_ref) {
|
|
|
34
33
|
codeBidiWarnings = _ref$codeBidiWarnings === void 0 ? true : _ref$codeBidiWarnings,
|
|
35
34
|
codeBidiWarningLabel = _ref.codeBidiWarningLabel,
|
|
36
35
|
_ref$codeBidiWarningT = _ref.codeBidiWarningTooltipEnabled,
|
|
37
|
-
codeBidiWarningTooltipEnabled = _ref$codeBidiWarningT === void 0 ? true : _ref$codeBidiWarningT
|
|
36
|
+
codeBidiWarningTooltipEnabled = _ref$codeBidiWarningT === void 0 ? true : _ref$codeBidiWarningT,
|
|
37
|
+
_ref$shouldWrapLongLi = _ref.shouldWrapLongLines,
|
|
38
|
+
shouldWrapLongLines = _ref$shouldWrapLongLi === void 0 ? false : _ref$shouldWrapLongLi;
|
|
38
39
|
var numLines = (text || '').split('\n').length;
|
|
39
40
|
var globalTheme = useGlobalTheme();
|
|
40
41
|
var theme = useMemo(function () {
|
|
@@ -44,8 +45,8 @@ var CodeBlock = /*#__PURE__*/memo(function CodeBlock(_ref) {
|
|
|
44
45
|
return getCodeBlockStyles(theme);
|
|
45
46
|
}, [theme]);
|
|
46
47
|
var styles = useMemo(function () {
|
|
47
|
-
return css(getStyles(highlightedStartText, highlightedEndText, showLineNumbers));
|
|
48
|
-
}, [highlightedStartText, highlightedEndText, showLineNumbers, getStyles]);
|
|
48
|
+
return css(getStyles(highlightedStartText, highlightedEndText, showLineNumbers, shouldWrapLongLines));
|
|
49
|
+
}, [highlightedStartText, highlightedEndText, showLineNumbers, shouldWrapLongLines, getStyles]);
|
|
49
50
|
var _useHighlightLines = useHighlightLines({
|
|
50
51
|
highlight: highlight,
|
|
51
52
|
testId: testId
|
|
@@ -61,25 +62,25 @@ var CodeBlock = /*#__PURE__*/memo(function CodeBlock(_ref) {
|
|
|
61
62
|
|
|
62
63
|
// https://product-fabric.atlassian.net/browse/DST-2472
|
|
63
64
|
var languageToUse = text ? language : 'text';
|
|
64
|
-
var renderer = codeBidiWarnings ? createBidiWarningRenderer({
|
|
65
|
-
codeBidiWarningLabel: codeBidiWarningLabel,
|
|
66
|
-
codeBidiWarningTooltipEnabled: codeBidiWarningTooltipEnabled
|
|
67
|
-
}) : undefined;
|
|
68
65
|
return jsx(SyntaxHighlighter, {
|
|
69
|
-
"data-testid": testId,
|
|
70
66
|
"data-code-lang": language,
|
|
71
67
|
"data-ds--code--code-block": "",
|
|
72
|
-
|
|
68
|
+
testId: testId,
|
|
73
69
|
language: languageToUse,
|
|
74
|
-
|
|
75
|
-
showLineNumbers: showLineNumbers
|
|
76
|
-
|
|
70
|
+
css: styles,
|
|
71
|
+
showLineNumbers: showLineNumbers,
|
|
72
|
+
lineProps: getLineProps
|
|
73
|
+
// shouldCreateParentElementForLines is needed to pass down props to each line.
|
|
74
|
+
// This is necessary for both line highlighting and testId's, as each of
|
|
75
|
+
// these rely on a data attribute being passed down to lines.
|
|
77
76
|
,
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
shouldCreateParentElementForLines: highlight.length > 0 || !!testId,
|
|
78
|
+
shouldWrapLongLines: shouldWrapLongLines,
|
|
79
|
+
codeBidiWarnings: codeBidiWarnings,
|
|
80
|
+
codeBidiWarningLabel: codeBidiWarningLabel,
|
|
81
|
+
codeBidiWarningTooltipEnabled: codeBidiWarningTooltipEnabled,
|
|
82
|
+
text: text
|
|
83
|
+
});
|
|
83
84
|
});
|
|
84
85
|
CodeBlock.displayName = 'CodeBlock';
|
|
85
86
|
export default CodeBlock;
|
|
@@ -27,7 +27,13 @@ var lineNumberStyle = function lineNumberStyle(theme) {
|
|
|
27
27
|
textAlign: 'right',
|
|
28
28
|
userSelect: 'none',
|
|
29
29
|
// this is to fix SSR spacing issue
|
|
30
|
-
display: 'block'
|
|
30
|
+
display: 'block',
|
|
31
|
+
// This is how we are preventing line numbers being copied to clipboard.
|
|
32
|
+
// (`user-select: none;` was not sufficent).
|
|
33
|
+
// https://product-fabric.atlassian.net/browse/DSP-2729
|
|
34
|
+
'&::after': {
|
|
35
|
+
content: "attr(data-ds--line-number)"
|
|
36
|
+
}
|
|
31
37
|
};
|
|
32
38
|
};
|
|
33
39
|
|
|
@@ -202,12 +208,12 @@ export var getBaseCodeStyles = function getBaseCodeStyles(theme) {
|
|
|
202
208
|
* @param theme
|
|
203
209
|
*/
|
|
204
210
|
export var getCodeBlockStyles = function getCodeBlockStyles(theme) {
|
|
205
|
-
return function (highlightedStartText, highlightedEndText,
|
|
211
|
+
return function (highlightedStartText, highlightedEndText, showLineNumbers, shouldWrapLongLines) {
|
|
206
212
|
return _objectSpread(_objectSpread(_objectSpread({
|
|
207
213
|
// this is required to account for prismjs styles leaking into the codeblock
|
|
208
214
|
'code[class*="language-"], pre[class*="language-"], code': {
|
|
209
215
|
all: 'unset',
|
|
210
|
-
padding:
|
|
216
|
+
padding: showLineNumbers ? "".concat(SPACING, "px 0") : SPACING
|
|
211
217
|
},
|
|
212
218
|
display: 'flex',
|
|
213
219
|
lineHeight: CODE_LINE_HEIGHT,
|
|
@@ -216,14 +222,14 @@ export var getCodeBlockStyles = function getCodeBlockStyles(theme) {
|
|
|
216
222
|
direction: 'ltr'
|
|
217
223
|
}, getBaseCodeStyles(theme)), syntaxKeywordColors(theme)), {}, {
|
|
218
224
|
// this is to account for SSR spacing issue once loaded in browser
|
|
219
|
-
'& .linenumber, .
|
|
225
|
+
'& .linenumber, .ds-sh-line-number': lineNumberStyle(theme),
|
|
220
226
|
'& .linenumber': {
|
|
221
227
|
display: 'inline-block !important',
|
|
222
228
|
float: 'left'
|
|
223
229
|
},
|
|
224
230
|
// these styles are for line highlighting
|
|
225
231
|
'& [data-ds--code--row]': {
|
|
226
|
-
display: 'block',
|
|
232
|
+
display: showLineNumbers ? 'flex' : 'block',
|
|
227
233
|
paddingRight: "".concat(SPACING, "px !important"),
|
|
228
234
|
marginRight: "-".concat(SPACING, "px")
|
|
229
235
|
},
|
|
@@ -239,11 +245,12 @@ export var getCodeBlockStyles = function getCodeBlockStyles(theme) {
|
|
|
239
245
|
whiteSpace: 'nowrap',
|
|
240
246
|
width: '1px'
|
|
241
247
|
},
|
|
248
|
+
// The formatting here is an accessibility convention
|
|
242
249
|
'&::before': {
|
|
243
|
-
content: "\"
|
|
250
|
+
content: "\" [".concat(highlightedStartText, "] \"")
|
|
244
251
|
},
|
|
245
252
|
'&::after': {
|
|
246
|
-
content: "\"
|
|
253
|
+
content: "\" [".concat(highlightedEndText, "] \"")
|
|
247
254
|
}
|
|
248
255
|
},
|
|
249
256
|
'& [data-ds--code--row--highlight] .linenumber': {
|
|
@@ -268,14 +275,18 @@ export var getCodeBlockStyles = function getCodeBlockStyles(theme) {
|
|
|
268
275
|
},
|
|
269
276
|
'& code:first-of-type': {
|
|
270
277
|
paddingRight: "0px !important",
|
|
271
|
-
backgroundImage:
|
|
278
|
+
backgroundImage: showLineNumbers ? "linear-gradient(to right, var(".concat(VAR_CODE_LINE_NUMBER_BG_COLOR, ",").concat(theme.lineNumberBgColor, "), var(").concat(VAR_CODE_LINE_NUMBER_BG_COLOR, ",").concat(theme.lineNumberBgColor, ")\n calc(").concat(theme.lineNumberWidth, " + ").concat(LINE_NUMBER_GUTTER, "px), transparent calc(").concat(theme.lineNumberWidth, " + ").concat(LINE_NUMBER_GUTTER, "px), transparent)") : undefined
|
|
272
279
|
},
|
|
273
280
|
// we need to use last-of-type because when Code is SSR'd
|
|
274
281
|
// 2 <code> elements are created and we don't want this style
|
|
275
282
|
// applied to the first one
|
|
276
283
|
'& code:last-of-type': {
|
|
277
284
|
paddingRight: "".concat(SPACING, "px !important"),
|
|
278
|
-
|
|
285
|
+
flexBasis: 'auto',
|
|
286
|
+
flexGrow: 1,
|
|
287
|
+
// Needed for the highlight line to extend full-width
|
|
288
|
+
flexShrink: shouldWrapLongLines ? 1 : 0,
|
|
289
|
+
wordBreak: 'break-word'
|
|
279
290
|
},
|
|
280
291
|
// Prevents empty code blocks from vertically collapsing
|
|
281
292
|
'code > span:only-child:empty:before, code > span:only-child > span:only-child:empty:before': {
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
3
|
+
import _createClass from "@babel/runtime/helpers/createClass";
|
|
4
|
+
import _inherits from "@babel/runtime/helpers/inherits";
|
|
5
|
+
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
|
|
6
|
+
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
|
|
7
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
8
|
+
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
|
9
|
+
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import highlight from './lib/highlight';
|
|
12
|
+
// Uses the loader method of async bundling
|
|
13
|
+
// Instantiates highligher as a singleton, loading refractor only once per page (refractor/prism are singleton modules)
|
|
14
|
+
var generator = function generator(options) {
|
|
15
|
+
var loader = options.loader;
|
|
16
|
+
|
|
17
|
+
// eslint-disable-next-line @repo/internal/react/no-class-components
|
|
18
|
+
var AsyncHighlighter = /*#__PURE__*/function (_React$PureComponent) {
|
|
19
|
+
_inherits(AsyncHighlighter, _React$PureComponent);
|
|
20
|
+
var _super = _createSuper(AsyncHighlighter);
|
|
21
|
+
function AsyncHighlighter() {
|
|
22
|
+
_classCallCheck(this, AsyncHighlighter);
|
|
23
|
+
return _super.apply(this, arguments);
|
|
24
|
+
}
|
|
25
|
+
_createClass(AsyncHighlighter, [{
|
|
26
|
+
key: "componentDidMount",
|
|
27
|
+
value: function componentDidMount() {
|
|
28
|
+
var _this = this;
|
|
29
|
+
if (!AsyncHighlighter.astGeneratorPromise) {
|
|
30
|
+
AsyncHighlighter.loadAstGenerator();
|
|
31
|
+
}
|
|
32
|
+
if (!AsyncHighlighter.astGenerator && AsyncHighlighter.astGeneratorPromise) {
|
|
33
|
+
AsyncHighlighter.astGeneratorPromise.then(function () {
|
|
34
|
+
_this.forceUpdate();
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}, {
|
|
39
|
+
key: "render",
|
|
40
|
+
value: function render() {
|
|
41
|
+
return /*#__PURE__*/React.createElement(AsyncHighlighter.highlightInstance, _extends({}, this.props, {
|
|
42
|
+
astGenerator: AsyncHighlighter.astGenerator
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
}], [{
|
|
46
|
+
key: "preload",
|
|
47
|
+
value:
|
|
48
|
+
// Useful in tests
|
|
49
|
+
function preload() {
|
|
50
|
+
return AsyncHighlighter.loadAstGenerator();
|
|
51
|
+
}
|
|
52
|
+
}, {
|
|
53
|
+
key: "loadAstGenerator",
|
|
54
|
+
value: function loadAstGenerator() {
|
|
55
|
+
AsyncHighlighter.astGeneratorPromise = loader().then(function (astGenerator) {
|
|
56
|
+
AsyncHighlighter.astGenerator = astGenerator;
|
|
57
|
+
return astGenerator;
|
|
58
|
+
});
|
|
59
|
+
return AsyncHighlighter.astGeneratorPromise;
|
|
60
|
+
}
|
|
61
|
+
}]);
|
|
62
|
+
return AsyncHighlighter;
|
|
63
|
+
}(React.PureComponent);
|
|
64
|
+
_defineProperty(AsyncHighlighter, "astGenerator", null);
|
|
65
|
+
_defineProperty(AsyncHighlighter, "highlightInstance", highlight);
|
|
66
|
+
return AsyncHighlighter;
|
|
67
|
+
};
|
|
68
|
+
export default generator({
|
|
69
|
+
loader: function loader() {
|
|
70
|
+
return import( /* webpackChunkName: "@atlaskit-internal_refractor-import" */
|
|
71
|
+
'refractor').then(function (module) {
|
|
72
|
+
// Webpack 3 returns module.exports as default as module, but webpack 4 returns module.exports as module.default
|
|
73
|
+
return module.default || module;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|