@readme/syntax-highlighter 15.0.3 → 16.0.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/dist/index.js +2 -47606
- package/dist/index.js.LICENSE.txt +66 -0
- package/dist/index.node.js +1 -394
- package/package.json +8 -5
- package/.babelrc +0 -13
- package/LICENSES +0 -23
- package/knip.ts +0 -22
- package/public/favicon.ico +0 -0
- package/public/index.html +0 -7
- package/public/index.js +0 -170
- package/public/index.legacy.js +0 -169
- package/src/codeEditor/cm.options.ts +0 -11
- package/src/codeEditor/index.tsx +0 -55
- package/src/codeEditor/style.scss +0 -6
- package/src/codeMirror/index.jsx +0 -260
- package/src/codeMirror/style.scss +0 -104
- package/src/index.js +0 -68
- package/src/index.node.ts +0 -5
- package/src/utils/canonical.ts +0 -65
- package/src/utils/cm-mode-imports.js +0 -33
- package/src/utils/index.ts +0 -5
- package/src/utils/modes/solidity.js +0 -605
- package/src/utils/modes.ts +0 -104
- package/src/utils/uppercase.ts +0 -111
- package/tsconfig.json +0 -13
- package/webpack.config.dev.js +0 -45
- package/webpack.config.js +0 -80
package/public/index.js
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import createRoot from 'react-dom/client';
|
|
3
|
-
|
|
4
|
-
import syntaxHighlighter, { cmVariableContext } from '../src/index';
|
|
5
|
-
|
|
6
|
-
const exampleCode = `curl --request POST
|
|
7
|
-
--url <<url>>
|
|
8
|
-
--header 'authorization: Bearer 123'
|
|
9
|
-
--header 'content-type: application/json'`;
|
|
10
|
-
|
|
11
|
-
const exampleJson = `{
|
|
12
|
-
"key": "value",
|
|
13
|
-
"array": [1, 2, 3],
|
|
14
|
-
"a": {
|
|
15
|
-
"b": {
|
|
16
|
-
"c": {
|
|
17
|
-
"d": "ok",
|
|
18
|
-
"e": "err"
|
|
19
|
-
},
|
|
20
|
-
"f": {
|
|
21
|
-
"g": "ok"
|
|
22
|
-
},
|
|
23
|
-
"h": {
|
|
24
|
-
"i": "ok"
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"j": {
|
|
28
|
-
"k": {
|
|
29
|
-
"l": "ok"
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
"isThing": true
|
|
34
|
-
}
|
|
35
|
-
`;
|
|
36
|
-
|
|
37
|
-
const exampleMarkdown = `# Custom Scrollbars
|
|
38
|
-
|
|
39
|
-
This is a piece of text that creates scrollbars
|
|
40
|
-
|
|
41
|
-
Lorem ipsum dolor sit amet, turpis nec facilisis neque vestibulum adipiscing, magna nunc est luctus orci a,
|
|
42
|
-
aliquam duis ad volutpat nostra. Vestibulum ultricies suspendisse commodo volutpat pede sed. Bibendum odio
|
|
43
|
-
dignissim, ad vitae mollis ac sed nibh quis, suspendisse diam, risus quas blandit phasellus luctus nec,
|
|
44
|
-
integer nunc vitae posuere scelerisque. Lobortis quam porta conubia nulla. Et nisl ac, imperdiet vitae ac.
|
|
45
|
-
Parturient sit. Et vestibulum euismod, rutrum nunc libero mauris purus convallis. Cum id adipiscing et eget
|
|
46
|
-
pretium rutrum, ultrices sapien magnis fringilla sit lorem, eu vitae scelerisque ipsum aliquet, magna sed
|
|
47
|
-
fusce vel.
|
|
48
|
-
|
|
49
|
-
Lectus ultricies libero dolor convallis, sed etiam vel hendrerit egestas viverra, at urna mauris, eget
|
|
50
|
-
vulputate dolor voluptatem, nulla eget sollicitudin. Sed tincidunt, elit sociis. Mattis mi tortor dui id
|
|
51
|
-
sodales mi, maecenas nam fringilla risus turpis mauris praesent, imperdiet maecenas ultrices nonummy tellus
|
|
52
|
-
quis est. Scelerisque nec pharetra quis varius fringilla. Varius vestibulum non dictum pharetra, tincidunt in
|
|
53
|
-
vestibulum iaculis molestie, id condimentum blandit elit urna magna pulvinar, quam suspendisse pellentesque
|
|
54
|
-
donec. Vel amet ad ac. Nec aut viverra, morbi mi neque massa, turpis enim proin. Tellus eu, fermentum velit
|
|
55
|
-
est convallis aliquam velit, rutrum in diam lacus, praesent tempor pellentesque dictum semper augue. Felis
|
|
56
|
-
explicabo massa amet lectus phasellus dolor. Ut lorem quis arcu neque felis ultricies, senectus vitae
|
|
57
|
-
curabitur sed pellentesque et, id sed risus in sed ac accumsan, blandit arcu quam duis nunc.
|
|
58
|
-
|
|
59
|
-
Sed leo sollicitudin odio vitae, purus sit egestas, justo eros inceptos auctor fermentum lectus. Ligula luctus
|
|
60
|
-
turpis, quod massa vitae elementum orci, nullam fringilla elit tortor. Justo ante tempor amet quam posuere
|
|
61
|
-
volutpat. Facilisis pede erat ut hac ultrices ipsum, wisi duis sit metus. Dolor vitae est sed sed vitae. Sed
|
|
62
|
-
eu ligula, morbi vestibulum nunc nibh velit ut taciti, ligula elit semper sagittis in, auctor arcu vel eget.
|
|
63
|
-
Mauris at vitae nec suspendisse et, aenean proin blandit suscipit. Morbi quam, dolor ultricies. Viverra
|
|
64
|
-
tempus. Suspendisse sit dapibus, ac fuga aenean, magna nisl nonummy augue posuere, dictum ut fuga velit
|
|
65
|
-
parturient augue interdum, mattis sit tellus.
|
|
66
|
-
|
|
67
|
-
Vehicula commodo tempus curabitur eros, lacinia erat vulputate lorem vel fermentum donec, lectus sed conubia
|
|
68
|
-
id pellentesque. Vel senectus donec pede aliquet dolor sit, nec vivamus justo placerat interdum maecenas,
|
|
69
|
-
sodales euismod. Quis netus sapien amet, vestibulum quam nec amet lacinia, quis aliquet, tempor vivamus tellus
|
|
70
|
-
enim, suscipit quis eleifend. Amet class phasellus orci pretium, risus in nulla. Neque sit ullamcorper,
|
|
71
|
-
ultricies platea id nec suspendisse ac. Et elementum. Dictum nam, ut dui fermentum egestas facilisis elit
|
|
72
|
-
augue, adipiscing donec ipsum erat nam pellentesque convallis, vestibulum vestibulum risus id nulla ut mauris,
|
|
73
|
-
curabitur aute aptent. Ultrices orci wisi dui ipsum praesent, pharetra felis eu quis. Est fringilla etiam,
|
|
74
|
-
maxime sem dapibus et eget, mi enim dignissim nec pretium, augue vehicula, volutpat proin. Et occaecati
|
|
75
|
-
lobortis viverra, cum in sed, vivamus tellus. Libero at malesuada est vivamus leo tortor.`;
|
|
76
|
-
|
|
77
|
-
const App = () => (
|
|
78
|
-
<div style={{ margin: '20px' }}>
|
|
79
|
-
<h1>Core Syntax Highlighter</h1>
|
|
80
|
-
|
|
81
|
-
<h2>Dark Theme</h2>
|
|
82
|
-
<pre id="hub-reference">
|
|
83
|
-
<cmVariableContext.Provider
|
|
84
|
-
value={{
|
|
85
|
-
user: {},
|
|
86
|
-
defaults: [
|
|
87
|
-
{
|
|
88
|
-
name: 'url',
|
|
89
|
-
default: 'GET',
|
|
90
|
-
},
|
|
91
|
-
],
|
|
92
|
-
}}
|
|
93
|
-
>
|
|
94
|
-
{syntaxHighlighter(exampleCode, 'curl', {
|
|
95
|
-
dark: true,
|
|
96
|
-
highlightMode: true,
|
|
97
|
-
tokenizeVariables: true,
|
|
98
|
-
ranges: [
|
|
99
|
-
[
|
|
100
|
-
{ ch: 0, line: 0 },
|
|
101
|
-
{ ch: 0, line: 1 },
|
|
102
|
-
],
|
|
103
|
-
[
|
|
104
|
-
{ ch: 0, line: 4 },
|
|
105
|
-
{ ch: 0, line: 5 },
|
|
106
|
-
],
|
|
107
|
-
],
|
|
108
|
-
})}
|
|
109
|
-
</cmVariableContext.Provider>
|
|
110
|
-
</pre>
|
|
111
|
-
|
|
112
|
-
<h2>Light Theme</h2>
|
|
113
|
-
<pre id="hub-reference">
|
|
114
|
-
<cmVariableContext.Provider
|
|
115
|
-
value={{
|
|
116
|
-
user: {},
|
|
117
|
-
defaults: [
|
|
118
|
-
{
|
|
119
|
-
name: 'url',
|
|
120
|
-
default: 'GET',
|
|
121
|
-
},
|
|
122
|
-
],
|
|
123
|
-
}}
|
|
124
|
-
>
|
|
125
|
-
{syntaxHighlighter(exampleCode, 'curl', {
|
|
126
|
-
dark: false,
|
|
127
|
-
highlightMode: true,
|
|
128
|
-
tokenizeVariables: true,
|
|
129
|
-
ranges: [
|
|
130
|
-
[
|
|
131
|
-
{ ch: 0, line: 0 },
|
|
132
|
-
{ ch: 0, line: 1 },
|
|
133
|
-
],
|
|
134
|
-
[
|
|
135
|
-
{ ch: 0, line: 4 },
|
|
136
|
-
{ ch: 0, line: 5 },
|
|
137
|
-
],
|
|
138
|
-
],
|
|
139
|
-
})}
|
|
140
|
-
</cmVariableContext.Provider>
|
|
141
|
-
</pre>
|
|
142
|
-
|
|
143
|
-
<hr />
|
|
144
|
-
<h1>Code Editor</h1>
|
|
145
|
-
<h2>Dark Theme</h2>
|
|
146
|
-
<pre id="hub-reference">
|
|
147
|
-
{syntaxHighlighter(exampleMarkdown, 'md', { scrollbarStyle: 'overlay', editable: true, dark: true })}
|
|
148
|
-
</pre>
|
|
149
|
-
|
|
150
|
-
<h2>Light Theme</h2>
|
|
151
|
-
<pre id="hub-reference">
|
|
152
|
-
{syntaxHighlighter(exampleMarkdown, 'md', { scrollbarStyle: 'overlay', editable: true, dark: false })}
|
|
153
|
-
</pre>
|
|
154
|
-
|
|
155
|
-
<hr />
|
|
156
|
-
<h1>Code Folding</h1>
|
|
157
|
-
<h2>Dark Theme</h2>
|
|
158
|
-
<pre id="hub-reference">
|
|
159
|
-
{syntaxHighlighter(exampleJson, 'json', { foldGutter: true, readOnly: true, dark: true })}
|
|
160
|
-
</pre>
|
|
161
|
-
|
|
162
|
-
<h2>Light Theme</h2>
|
|
163
|
-
<pre id="hub-reference">
|
|
164
|
-
{syntaxHighlighter(exampleJson, 'json', { foldGutter: true, readOnly: true, dark: false })}
|
|
165
|
-
</pre>
|
|
166
|
-
</div>
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
const root = createRoot(document.getElementById('root'));
|
|
170
|
-
root.render(<App />);
|
package/public/index.legacy.js
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import ReactDOM from 'react-dom';
|
|
3
|
-
|
|
4
|
-
import syntaxHighlighter, { cmVariableContext } from '../src/index';
|
|
5
|
-
|
|
6
|
-
const exampleCode = `curl --request POST
|
|
7
|
-
--url <<url>>
|
|
8
|
-
--header 'authorization: Bearer 123'
|
|
9
|
-
--header 'content-type: application/json'`;
|
|
10
|
-
|
|
11
|
-
const exampleJson = `{
|
|
12
|
-
"key": "value",
|
|
13
|
-
"array": [1, 2, 3],
|
|
14
|
-
"a": {
|
|
15
|
-
"b": {
|
|
16
|
-
"c": {
|
|
17
|
-
"d": "ok",
|
|
18
|
-
"e": "err"
|
|
19
|
-
},
|
|
20
|
-
"f": {
|
|
21
|
-
"g": "ok"
|
|
22
|
-
},
|
|
23
|
-
"h": {
|
|
24
|
-
"i": "ok"
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"j": {
|
|
28
|
-
"k": {
|
|
29
|
-
"l": "ok"
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
"isThing": true
|
|
34
|
-
}
|
|
35
|
-
`;
|
|
36
|
-
|
|
37
|
-
const exampleMarkdown = `# Custom Scrollbars
|
|
38
|
-
|
|
39
|
-
This is a piece of text that creates scrollbars
|
|
40
|
-
|
|
41
|
-
Lorem ipsum dolor sit amet, turpis nec facilisis neque vestibulum adipiscing, magna nunc est luctus orci a,
|
|
42
|
-
aliquam duis ad volutpat nostra. Vestibulum ultricies suspendisse commodo volutpat pede sed. Bibendum odio
|
|
43
|
-
dignissim, ad vitae mollis ac sed nibh quis, suspendisse diam, risus quas blandit phasellus luctus nec,
|
|
44
|
-
integer nunc vitae posuere scelerisque. Lobortis quam porta conubia nulla. Et nisl ac, imperdiet vitae ac.
|
|
45
|
-
Parturient sit. Et vestibulum euismod, rutrum nunc libero mauris purus convallis. Cum id adipiscing et eget
|
|
46
|
-
pretium rutrum, ultrices sapien magnis fringilla sit lorem, eu vitae scelerisque ipsum aliquet, magna sed
|
|
47
|
-
fusce vel.
|
|
48
|
-
|
|
49
|
-
Lectus ultricies libero dolor convallis, sed etiam vel hendrerit egestas viverra, at urna mauris, eget
|
|
50
|
-
vulputate dolor voluptatem, nulla eget sollicitudin. Sed tincidunt, elit sociis. Mattis mi tortor dui id
|
|
51
|
-
sodales mi, maecenas nam fringilla risus turpis mauris praesent, imperdiet maecenas ultrices nonummy tellus
|
|
52
|
-
quis est. Scelerisque nec pharetra quis varius fringilla. Varius vestibulum non dictum pharetra, tincidunt in
|
|
53
|
-
vestibulum iaculis molestie, id condimentum blandit elit urna magna pulvinar, quam suspendisse pellentesque
|
|
54
|
-
donec. Vel amet ad ac. Nec aut viverra, morbi mi neque massa, turpis enim proin. Tellus eu, fermentum velit
|
|
55
|
-
est convallis aliquam velit, rutrum in diam lacus, praesent tempor pellentesque dictum semper augue. Felis
|
|
56
|
-
explicabo massa amet lectus phasellus dolor. Ut lorem quis arcu neque felis ultricies, senectus vitae
|
|
57
|
-
curabitur sed pellentesque et, id sed risus in sed ac accumsan, blandit arcu quam duis nunc.
|
|
58
|
-
|
|
59
|
-
Sed leo sollicitudin odio vitae, purus sit egestas, justo eros inceptos auctor fermentum lectus. Ligula luctus
|
|
60
|
-
turpis, quod massa vitae elementum orci, nullam fringilla elit tortor. Justo ante tempor amet quam posuere
|
|
61
|
-
volutpat. Facilisis pede erat ut hac ultrices ipsum, wisi duis sit metus. Dolor vitae est sed sed vitae. Sed
|
|
62
|
-
eu ligula, morbi vestibulum nunc nibh velit ut taciti, ligula elit semper sagittis in, auctor arcu vel eget.
|
|
63
|
-
Mauris at vitae nec suspendisse et, aenean proin blandit suscipit. Morbi quam, dolor ultricies. Viverra
|
|
64
|
-
tempus. Suspendisse sit dapibus, ac fuga aenean, magna nisl nonummy augue posuere, dictum ut fuga velit
|
|
65
|
-
parturient augue interdum, mattis sit tellus.
|
|
66
|
-
|
|
67
|
-
Vehicula commodo tempus curabitur eros, lacinia erat vulputate lorem vel fermentum donec, lectus sed conubia
|
|
68
|
-
id pellentesque. Vel senectus donec pede aliquet dolor sit, nec vivamus justo placerat interdum maecenas,
|
|
69
|
-
sodales euismod. Quis netus sapien amet, vestibulum quam nec amet lacinia, quis aliquet, tempor vivamus tellus
|
|
70
|
-
enim, suscipit quis eleifend. Amet class phasellus orci pretium, risus in nulla. Neque sit ullamcorper,
|
|
71
|
-
ultricies platea id nec suspendisse ac. Et elementum. Dictum nam, ut dui fermentum egestas facilisis elit
|
|
72
|
-
augue, adipiscing donec ipsum erat nam pellentesque convallis, vestibulum vestibulum risus id nulla ut mauris,
|
|
73
|
-
curabitur aute aptent. Ultrices orci wisi dui ipsum praesent, pharetra felis eu quis. Est fringilla etiam,
|
|
74
|
-
maxime sem dapibus et eget, mi enim dignissim nec pretium, augue vehicula, volutpat proin. Et occaecati
|
|
75
|
-
lobortis viverra, cum in sed, vivamus tellus. Libero at malesuada est vivamus leo tortor.`;
|
|
76
|
-
|
|
77
|
-
const App = () => (
|
|
78
|
-
<div style={{ margin: '20px' }}>
|
|
79
|
-
<h1>Core Syntax Highlighter</h1>
|
|
80
|
-
|
|
81
|
-
<h2>Dark Theme</h2>
|
|
82
|
-
<pre id="hub-reference">
|
|
83
|
-
<cmVariableContext.Provider
|
|
84
|
-
value={{
|
|
85
|
-
user: {},
|
|
86
|
-
defaults: [
|
|
87
|
-
{
|
|
88
|
-
name: 'url',
|
|
89
|
-
default: 'GET',
|
|
90
|
-
},
|
|
91
|
-
],
|
|
92
|
-
}}
|
|
93
|
-
>
|
|
94
|
-
{syntaxHighlighter(exampleCode, 'curl', {
|
|
95
|
-
dark: true,
|
|
96
|
-
highlightMode: true,
|
|
97
|
-
tokenizeVariables: true,
|
|
98
|
-
ranges: [
|
|
99
|
-
[
|
|
100
|
-
{ ch: 0, line: 0 },
|
|
101
|
-
{ ch: 0, line: 1 },
|
|
102
|
-
],
|
|
103
|
-
[
|
|
104
|
-
{ ch: 0, line: 4 },
|
|
105
|
-
{ ch: 0, line: 5 },
|
|
106
|
-
],
|
|
107
|
-
],
|
|
108
|
-
})}
|
|
109
|
-
</cmVariableContext.Provider>
|
|
110
|
-
</pre>
|
|
111
|
-
|
|
112
|
-
<h2>Light Theme</h2>
|
|
113
|
-
<pre id="hub-reference">
|
|
114
|
-
<cmVariableContext.Provider
|
|
115
|
-
value={{
|
|
116
|
-
user: {},
|
|
117
|
-
defaults: [
|
|
118
|
-
{
|
|
119
|
-
name: 'url',
|
|
120
|
-
default: 'GET',
|
|
121
|
-
},
|
|
122
|
-
],
|
|
123
|
-
}}
|
|
124
|
-
>
|
|
125
|
-
{syntaxHighlighter(exampleCode, 'curl', {
|
|
126
|
-
dark: false,
|
|
127
|
-
highlightMode: true,
|
|
128
|
-
tokenizeVariables: true,
|
|
129
|
-
ranges: [
|
|
130
|
-
[
|
|
131
|
-
{ ch: 0, line: 0 },
|
|
132
|
-
{ ch: 0, line: 1 },
|
|
133
|
-
],
|
|
134
|
-
[
|
|
135
|
-
{ ch: 0, line: 4 },
|
|
136
|
-
{ ch: 0, line: 5 },
|
|
137
|
-
],
|
|
138
|
-
],
|
|
139
|
-
})}
|
|
140
|
-
</cmVariableContext.Provider>
|
|
141
|
-
</pre>
|
|
142
|
-
|
|
143
|
-
<hr />
|
|
144
|
-
<h1>Code Editor</h1>
|
|
145
|
-
<h2>Dark Theme</h2>
|
|
146
|
-
<pre id="hub-reference">
|
|
147
|
-
{syntaxHighlighter(exampleMarkdown, 'md', { scrollbarStyle: 'overlay', editable: true, dark: true })}
|
|
148
|
-
</pre>
|
|
149
|
-
|
|
150
|
-
<h2>Light Theme</h2>
|
|
151
|
-
<pre id="hub-reference">
|
|
152
|
-
{syntaxHighlighter(exampleMarkdown, 'md', { scrollbarStyle: 'overlay', editable: true, dark: false })}
|
|
153
|
-
</pre>
|
|
154
|
-
|
|
155
|
-
<hr />
|
|
156
|
-
<h1>Code Folding</h1>
|
|
157
|
-
<h2>Dark Theme</h2>
|
|
158
|
-
<pre id="hub-reference">
|
|
159
|
-
{syntaxHighlighter(exampleJson, 'json', { foldGutter: true, readOnly: true, dark: true })}
|
|
160
|
-
</pre>
|
|
161
|
-
|
|
162
|
-
<h2>Light Theme</h2>
|
|
163
|
-
<pre id="hub-reference">
|
|
164
|
-
{syntaxHighlighter(exampleJson, 'json', { foldGutter: true, readOnly: true, dark: false })}
|
|
165
|
-
</pre>
|
|
166
|
-
</div>
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
ReactDOM.render(<App />, document.getElementById('root'));
|
package/src/codeEditor/index.tsx
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type { ICodeMirror } from 'react-codemirror2';
|
|
2
|
-
|
|
3
|
-
import React, { useEffect, useState } from 'react';
|
|
4
|
-
import { Controlled as CodeMirror } from 'react-codemirror2';
|
|
5
|
-
|
|
6
|
-
import '../utils/cm-mode-imports';
|
|
7
|
-
import { getMode } from '../utils/modes';
|
|
8
|
-
|
|
9
|
-
import defaults from './cm.options';
|
|
10
|
-
import './style.scss';
|
|
11
|
-
|
|
12
|
-
const CodeEditor: React.FC<{
|
|
13
|
-
children?: string;
|
|
14
|
-
className?: string;
|
|
15
|
-
code?: string;
|
|
16
|
-
lang?: string;
|
|
17
|
-
options?: ICodeMirror['options'];
|
|
18
|
-
theme?: 'material-palenight' | 'neo' | 'tomorrow-night';
|
|
19
|
-
}> = ({
|
|
20
|
-
className = '', // unused, I think on purpose? but not sure
|
|
21
|
-
code = '',
|
|
22
|
-
lang,
|
|
23
|
-
options = {},
|
|
24
|
-
children,
|
|
25
|
-
theme = 'material-palenight',
|
|
26
|
-
...attr
|
|
27
|
-
}) => {
|
|
28
|
-
const [value, setValue] = useState(children && typeof children === 'string' ? children : code);
|
|
29
|
-
const [mode, setMode] = useState(getMode(lang as string));
|
|
30
|
-
|
|
31
|
-
useEffect(() => {
|
|
32
|
-
const incValue = children && typeof children === 'string' ? children : code;
|
|
33
|
-
setValue(incValue);
|
|
34
|
-
}, [code, children]);
|
|
35
|
-
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
setMode(prevMode => {
|
|
38
|
-
const newMode = getMode(lang as string);
|
|
39
|
-
if (newMode !== prevMode) return newMode;
|
|
40
|
-
return prevMode;
|
|
41
|
-
});
|
|
42
|
-
}, [lang]);
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
<CodeMirror
|
|
46
|
-
{...attr}
|
|
47
|
-
className="CodeEditor"
|
|
48
|
-
onBeforeChange={(editor, data, updatedCode) => setValue(updatedCode)}
|
|
49
|
-
options={{ ...defaults, ...options, mode, theme }}
|
|
50
|
-
value={value as string}
|
|
51
|
-
/>
|
|
52
|
-
);
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export default CodeEditor;
|
package/src/codeMirror/index.jsx
DELETED
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
import Variable, { MDX_VARIABLE_REGEXP, VARIABLE_REGEXP, VariablesContext } from '@readme/variable';
|
|
2
|
-
import CodeMirror from 'codemirror';
|
|
3
|
-
import 'codemirror/addon/fold/brace-fold';
|
|
4
|
-
import 'codemirror/addon/fold/foldgutter';
|
|
5
|
-
import 'codemirror/addon/runmode/runmode';
|
|
6
|
-
import 'codemirror/addon/scroll/simplescrollbars';
|
|
7
|
-
import 'codemirror/addon/scroll/simplescrollbars.css';
|
|
8
|
-
import 'codemirror/mode/meta';
|
|
9
|
-
import PropTypes from 'prop-types';
|
|
10
|
-
import React from 'react';
|
|
11
|
-
|
|
12
|
-
import '../utils/cm-mode-imports';
|
|
13
|
-
import { getMode } from '../utils/modes.ts';
|
|
14
|
-
|
|
15
|
-
import './style.scss';
|
|
16
|
-
|
|
17
|
-
// Pre output conversion
|
|
18
|
-
// CodeMirror "Gutter" -> Apply line numbers to styled lines
|
|
19
|
-
const defaultLineJsx = line => (
|
|
20
|
-
<span key={`ln-${line}`} className="cm-lineNumber">
|
|
21
|
-
{line}
|
|
22
|
-
</span>
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
// Wrap children elements, seperated by line into divs
|
|
26
|
-
// Simple styling wrapper
|
|
27
|
-
const WrappedLine = ({ className, child }) => <div className={className}>{child}</div>;
|
|
28
|
-
|
|
29
|
-
WrappedLine.propTypes = {
|
|
30
|
-
child: PropTypes.any,
|
|
31
|
-
className: PropTypes.string,
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// Final Styled Output
|
|
35
|
-
// Includes Highlighted | Overlayed | null styled lines
|
|
36
|
-
const StructuredOutput = ({ gutteredInput, highlights = [] }) =>
|
|
37
|
-
gutteredInput.map((ac, idx) => {
|
|
38
|
-
return (
|
|
39
|
-
<WrappedLine
|
|
40
|
-
key={`cm-wrapped-${idx}`}
|
|
41
|
-
child={ac}
|
|
42
|
-
className={['cm-linerow', highlights.length ? highlights[idx] : ''].join(' ')}
|
|
43
|
-
/>
|
|
44
|
-
);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
StructuredOutput.propTypes = {
|
|
48
|
-
gutteredInput: PropTypes.any,
|
|
49
|
-
highlights: PropTypes.arrayOf(PropTypes.string),
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Generate an array of classNames
|
|
54
|
-
*
|
|
55
|
-
* @arg {[][]{line: Int}} ranges
|
|
56
|
-
* @return {[String]} Consumable classNames
|
|
57
|
-
*/
|
|
58
|
-
const highlightedLines = (ranges, totalLength) => {
|
|
59
|
-
const highlights = [];
|
|
60
|
-
|
|
61
|
-
ranges.forEach(([anchor, head]) => {
|
|
62
|
-
const end = head.line;
|
|
63
|
-
let position = anchor.line;
|
|
64
|
-
|
|
65
|
-
while (position < end) {
|
|
66
|
-
highlights[position] = 'cm-highlight';
|
|
67
|
-
position += 1;
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
for (let i = 0; i < totalLength; i += 1) {
|
|
72
|
-
if (!highlights[i]) highlights[i] = 'cm-overlay';
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return highlights;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const StyledSyntaxHighlighter = ({ output, ranges }) => {
|
|
79
|
-
const lineBreakRegex = /\r?\n/;
|
|
80
|
-
const gutteredOutput = [];
|
|
81
|
-
let bucket = [];
|
|
82
|
-
let lineNumber = 1;
|
|
83
|
-
|
|
84
|
-
const incrementLine = newLine => {
|
|
85
|
-
// If new line, we'll manually add it to a bucket
|
|
86
|
-
if (newLine) bucket.push('\n');
|
|
87
|
-
// Regardless, we'll add the bucket to our larger output and start a new numbered div
|
|
88
|
-
gutteredOutput.push(bucket);
|
|
89
|
-
lineNumber += 1;
|
|
90
|
-
bucket = [defaultLineJsx(lineNumber)];
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const enumerateMatches = (o, final) => {
|
|
94
|
-
// Case where a single line break
|
|
95
|
-
if (o.length === 1 && lineBreakRegex.test(o)) {
|
|
96
|
-
incrementLine(true);
|
|
97
|
-
// Case with multiple consecutive line breaks
|
|
98
|
-
} else {
|
|
99
|
-
const matches = o.split(lineBreakRegex);
|
|
100
|
-
matches.forEach(m => {
|
|
101
|
-
if (m.length) {
|
|
102
|
-
bucket.push(m);
|
|
103
|
-
// If we've found a match right before the end of our output, we pad it
|
|
104
|
-
if (final) incrementLine();
|
|
105
|
-
} else {
|
|
106
|
-
incrementLine(true);
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
output.unshift(defaultLineJsx(1));
|
|
113
|
-
output.forEach((o, idx) => {
|
|
114
|
-
if (idx === output.length - 1) {
|
|
115
|
-
if (typeof o === 'string') enumerateMatches(o, true);
|
|
116
|
-
else {
|
|
117
|
-
bucket.push(o);
|
|
118
|
-
gutteredOutput.push(bucket);
|
|
119
|
-
}
|
|
120
|
-
} else if (!lineBreakRegex.test(o)) {
|
|
121
|
-
bucket.push(o);
|
|
122
|
-
} else if (typeof o === 'string') {
|
|
123
|
-
enumerateMatches(o);
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
const highlights = ranges && ranges.length ? highlightedLines(ranges, gutteredOutput.length) : [];
|
|
128
|
-
return (
|
|
129
|
-
<div className="CodeMirror" data-testid="CodeMirror">
|
|
130
|
-
<StructuredOutput gutteredInput={gutteredOutput} highlights={highlights} />
|
|
131
|
-
</div>
|
|
132
|
-
);
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
/*
|
|
136
|
-
* ReadMe user variables are written like <<var>>. Depending on the
|
|
137
|
-
* language parser used by CodeMirror, that could get parsed into
|
|
138
|
-
* multiple tokens, ie ['<<', 'var', '>>']. So, we do a first pass to
|
|
139
|
-
* remove the variables. And reinsert them after CodeMirror has done its
|
|
140
|
-
* parsing.
|
|
141
|
-
*/
|
|
142
|
-
const makeReinserter = variables => {
|
|
143
|
-
let offset = 0;
|
|
144
|
-
let variable = variables.shift();
|
|
145
|
-
|
|
146
|
-
const reinsertVariables = token => {
|
|
147
|
-
if (!variable) return token;
|
|
148
|
-
|
|
149
|
-
if (offset <= variable.offset && variable.offset <= offset + token.length) {
|
|
150
|
-
const tokenOffset = variable.offset - offset;
|
|
151
|
-
const [before, after] = [token.slice(0, tokenOffset), token.slice(tokenOffset)];
|
|
152
|
-
const variableComponent = <Variable key={`variable-${offset}`} variable={variable.text} />;
|
|
153
|
-
|
|
154
|
-
offset += tokenOffset;
|
|
155
|
-
variable = variables.shift();
|
|
156
|
-
|
|
157
|
-
return [before, variableComponent, reinsertVariables(after)];
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
offset += token.length;
|
|
161
|
-
return token;
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
return reinsertVariables;
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const extractVariables = (code, opts) => {
|
|
168
|
-
if (!opts.tokenizeVariables) return [code, text => text];
|
|
169
|
-
|
|
170
|
-
let offsetDelta = 0;
|
|
171
|
-
const variables = [];
|
|
172
|
-
|
|
173
|
-
const extracter = (match, ...rest) => {
|
|
174
|
-
const unescaped = opts.mdx
|
|
175
|
-
? match.replace(/^\\{/, '{').replace(/\\}$/, '}')
|
|
176
|
-
: match.replace(/^\\<</, '<<').replace(/\\>>$/, '>>');
|
|
177
|
-
|
|
178
|
-
if (unescaped !== match) {
|
|
179
|
-
return unescaped;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const capture = rest[opts.mdx ? 1 : 0];
|
|
183
|
-
const offset = rest[opts.mdx ? 3 : 1];
|
|
184
|
-
|
|
185
|
-
variables.push({ text: capture, offset: offset - offsetDelta });
|
|
186
|
-
offsetDelta += match.length;
|
|
187
|
-
|
|
188
|
-
return '';
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
const regexp = opts.mdx ? MDX_VARIABLE_REGEXP : VARIABLE_REGEXP;
|
|
192
|
-
const codeWithoutVars = code.replace(new RegExp(regexp, 'g'), extracter);
|
|
193
|
-
|
|
194
|
-
return [codeWithoutVars, makeReinserter(variables)];
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
StyledSyntaxHighlighter.propTypes = {
|
|
198
|
-
output: PropTypes.arrayOf(PropTypes.any),
|
|
199
|
-
ranges: PropTypes.arrayOf(PropTypes.any),
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Core Syntax Highlighter
|
|
204
|
-
* @arg {String} code
|
|
205
|
-
* @arg {String} lang
|
|
206
|
-
* @arg {{}} opts
|
|
207
|
-
* @return {[Element]} Array of DOM Elements
|
|
208
|
-
*/
|
|
209
|
-
const ReadmeCodeMirror = (
|
|
210
|
-
code,
|
|
211
|
-
lang,
|
|
212
|
-
opts = { tokenizeVariables: false, highlightMode: false, ranges: [] },
|
|
213
|
-
{ mdx = false } = {},
|
|
214
|
-
) => {
|
|
215
|
-
const mode = getMode(lang);
|
|
216
|
-
const output = [];
|
|
217
|
-
|
|
218
|
-
const [codeWithoutVars, reinsertVariables] = extractVariables(code, { scrollbarStyle: 'overlay', mdx, ...opts });
|
|
219
|
-
|
|
220
|
-
let curStyle = null;
|
|
221
|
-
let accum = '';
|
|
222
|
-
let key = 0;
|
|
223
|
-
|
|
224
|
-
function flush() {
|
|
225
|
-
const token = reinsertVariables(accum);
|
|
226
|
-
|
|
227
|
-
const styledToken = curStyle ? (
|
|
228
|
-
// oxlint-disable-next-line no-plusplus
|
|
229
|
-
<span key={key++} className={`${curStyle.replace(/(^|\s+)/g, '$1cm-')}`}>
|
|
230
|
-
{token}
|
|
231
|
-
</span>
|
|
232
|
-
) : (
|
|
233
|
-
token
|
|
234
|
-
);
|
|
235
|
-
|
|
236
|
-
output.push(styledToken);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
CodeMirror.runMode(codeWithoutVars, mode, (text, style) => {
|
|
240
|
-
const lineBreakRegex = /\r?\n/;
|
|
241
|
-
if (style !== curStyle || (opts.highlightMode && lineBreakRegex.test(text))) {
|
|
242
|
-
flush();
|
|
243
|
-
curStyle = style;
|
|
244
|
-
accum = text;
|
|
245
|
-
} else {
|
|
246
|
-
accum += text;
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
flush();
|
|
250
|
-
|
|
251
|
-
// Return legacy DOM structure
|
|
252
|
-
// Array of <span /> elements
|
|
253
|
-
if (!opts.highlightMode) return output;
|
|
254
|
-
// Return Codemirror-Styled DOM structure
|
|
255
|
-
// Includes line numbers, styling, optional highlighting
|
|
256
|
-
return <StyledSyntaxHighlighter output={output} ranges={opts.ranges} />;
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
export default ReadmeCodeMirror;
|
|
260
|
-
export { VariablesContext };
|