@salesforcedevs/dx-components 1.18.6 → 1.18.8-layoutfix-alpha
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/package.json +4 -4
- package/src/modules/dx/codeBlock/codeBlock.css +16 -10
- package/src/modules/dx/codeBlock/codeBlock.ts +81 -71
- package/src/modules/dx/toc/toc.css +1 -1
- package/src/modules/dxHelpers/code/code.css +19 -87
- package/src/modules/dxUtils/shiki/__mocks__/shiki.ts +110 -0
- package/src/modules/dxUtils/shiki/__mocks__/shikijs.ts +23 -0
- package/src/modules/dxUtils/shiki/customLanguages/afscript.tmLanguage.json +855 -0
- package/src/modules/dxUtils/shiki/customLanguages/ampscript.tmLanguage.json +176 -0
- package/src/modules/dxUtils/shiki/customLanguages/dataweave.tmLanguage.json +1130 -0
- package/src/modules/dxUtils/shiki/shiki.html +3 -0
- package/src/modules/dxUtils/shiki/shiki.ts +210 -0
- package/LICENSE +0 -12
- package/src/modules/dx/codeBlock/customLanguages.js +0 -48
- package/src/modules/dx/codeBlock/darkAndLightThemes.css +0 -177
- package/src/modules/dxUtils/prismjs/prismjs.html +0 -3
- package/src/modules/dxUtils/prismjs/prismjs.ts +0 -4183
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforcedevs/dx-components",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.8-layoutfix-alpha",
|
|
4
4
|
"description": "DX Lightning web components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"@coveo/headless": "3.22.2",
|
|
14
14
|
"@floating-ui/dom": "1.5.1",
|
|
15
15
|
"@optimizely/optimizely-sdk": "5.3.0",
|
|
16
|
-
"@
|
|
16
|
+
"@shikijs/colorized-brackets": "^3.12.2",
|
|
17
17
|
"@types/throttle-debounce": "5.0.2",
|
|
18
18
|
"@vimeo/player": "2.22.0",
|
|
19
19
|
"classnames": "2.5.1",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"lodash.kebabcase": "4.1.1",
|
|
27
27
|
"memoize-one": "6.0.0",
|
|
28
28
|
"microtip": "0.2.2",
|
|
29
|
+
"shiki": "^3.12.2",
|
|
29
30
|
"throttle-debounce": "5.0.0",
|
|
30
31
|
"uuid": "9.0.1"
|
|
31
32
|
},
|
|
@@ -44,6 +45,5 @@
|
|
|
44
45
|
},
|
|
45
46
|
"volta": {
|
|
46
47
|
"node": "20.19.0"
|
|
47
|
-
}
|
|
48
|
-
"gitHead": "a96577b729c567b862754304eee2b3ad489b3765"
|
|
48
|
+
}
|
|
49
49
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
@import "dxHelpers/code";
|
|
2
2
|
@import "dxHelpers/text";
|
|
3
|
-
@import "./darkAndLightThemes.css";
|
|
4
3
|
|
|
5
4
|
:host {
|
|
6
5
|
position: relative;
|
|
@@ -89,6 +88,7 @@ div.dx-theme-light {
|
|
|
89
88
|
--dx-c-button-custom-color: #fff;
|
|
90
89
|
--dx-c-button-custom-color-hover: #fff;
|
|
91
90
|
--dx-c-button-custom-background-hover: var(--dx-g-blue-natural-10);
|
|
91
|
+
--dx-c-button-inline-color: #fff;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
.dx-theme-light .btn {
|
|
@@ -98,15 +98,15 @@ div.dx-theme-light {
|
|
|
98
98
|
--dx-c-button-custom-color: var(--dx-g-blue-vibrant-20);
|
|
99
99
|
--dx-c-button-custom-color-hover: var(--dx-g-blue-vibrant-20);
|
|
100
100
|
--dx-c-button-custom-background-hover: var(--dx-g-gray-60);
|
|
101
|
+
--dx-c-button-inline-color: var(--dx-g-blue-vibrant-20);
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
div.code-block-content {
|
|
104
105
|
border-radius: 0 0 0.3em 0.3em;
|
|
105
106
|
overflow-y: auto;
|
|
106
|
-
background: var(--prism-a11y-color-background);
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
code[class*="
|
|
109
|
+
code[class*="shiki"] {
|
|
110
110
|
margin-left: -11px;
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -114,14 +114,20 @@ code[class*="language-"] {
|
|
|
114
114
|
margin-right: var(--dx-g-spacing-xs);
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
pre[class*="
|
|
117
|
+
pre[class*="shiki"] {
|
|
118
118
|
border-radius: 0 0 0.3em 0.3em;
|
|
119
|
-
padding
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
119
|
+
padding: 1em;
|
|
120
|
+
margin: 0.5em 0;
|
|
121
|
+
overflow: auto;
|
|
122
|
+
/* stylelint-disable-next-line */
|
|
123
|
+
.line {
|
|
124
|
+
counter-increment: codeblock-line;
|
|
125
|
+
|
|
126
|
+
&::before {
|
|
127
|
+
content: counter(codeblock-line);
|
|
128
|
+
margin-right: 1.3em;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
125
131
|
}
|
|
126
132
|
|
|
127
133
|
@media screen and (max-width: 640px) {
|
|
@@ -2,35 +2,17 @@ import { LightningElement, api } from "lwc";
|
|
|
2
2
|
import { CodeBlockTheme, CodeBlockLanguage } from "typings/custom";
|
|
3
3
|
import cx from "classnames";
|
|
4
4
|
import { track as gtmTrack } from "dxUtils/analytics";
|
|
5
|
-
import
|
|
6
|
-
import { ampscript, sqlDocsTemplate } from "./customLanguages";
|
|
5
|
+
import { highlightCode } from "dxUtils/shiki";
|
|
7
6
|
|
|
8
7
|
/*
|
|
9
|
-
|
|
8
|
+
Custom language support is handled by the Shiki wrapper module
|
|
9
|
+
which maps proprietary languages to supported ones:
|
|
10
|
+
- AMPScript -> HTML (markup-like syntax)
|
|
11
|
+
- SSJS -> JavaScript
|
|
12
|
+
- GTL -> Handlebars
|
|
13
|
+
- LWC -> JavaScript/JSX
|
|
14
|
+
- SQL Documentation -> SQL
|
|
10
15
|
*/
|
|
11
|
-
// AMPScript
|
|
12
|
-
prism.languages.ampscript = prism.languages.extend("markup");
|
|
13
|
-
prism.languages.insertBefore("ampscript", "comment", { ampscript });
|
|
14
|
-
|
|
15
|
-
// SSJS (Server-Side JavaScript)
|
|
16
|
-
prism.languages.ssjs = prism.languages.extend("markup");
|
|
17
|
-
prism.languages.insertBefore("ssjs", "comment", { ampscript });
|
|
18
|
-
|
|
19
|
-
// GTL (Guide Template Language)
|
|
20
|
-
prism.languages.gtl = prism.languages.extend(
|
|
21
|
-
"markup",
|
|
22
|
-
prism.languages.handlebars
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
// LWC
|
|
26
|
-
prism.languages.lwc = prism.languages.extend("jsx");
|
|
27
|
-
|
|
28
|
-
/*
|
|
29
|
-
Prismjs's SQL native language rules doesn't highlight keyword like "RECURSIVE" and "WINDOW".
|
|
30
|
-
Instead of modifying the native SQL language rules, we create a new language called "sql_docs_template"
|
|
31
|
-
that treats all uppercase words as keywords.
|
|
32
|
-
*/
|
|
33
|
-
prism.languages.sql_docs_template = sqlDocsTemplate;
|
|
34
16
|
|
|
35
17
|
// Used for remove enclosing <pre> tag's (if occurs)
|
|
36
18
|
const preTagRegexp: RegExp = /^<pre.*?>(.*)<\/pre>$/is;
|
|
@@ -89,7 +71,8 @@ export default class CodeBlock extends LightningElement {
|
|
|
89
71
|
{ label: "SSJS", id: "ssjs" },
|
|
90
72
|
{ label: "GTL", id: "gtl" },
|
|
91
73
|
{ label: "LWC", id: "lwc" },
|
|
92
|
-
{ label: "SQL Documentation", id: "sql_docs_template" }
|
|
74
|
+
{ label: "SQL Documentation", id: "sql_docs_template" },
|
|
75
|
+
{ label: "Agentforce Script", id: "afscript" }
|
|
93
76
|
];
|
|
94
77
|
|
|
95
78
|
_codeBlock: string = "";
|
|
@@ -135,80 +118,100 @@ export default class CodeBlock extends LightningElement {
|
|
|
135
118
|
this.initializeTheme();
|
|
136
119
|
}
|
|
137
120
|
|
|
138
|
-
formatCodeBlock() {
|
|
121
|
+
async formatCodeBlock() {
|
|
139
122
|
const divEl = this.template.querySelector("div.code-block-content");
|
|
140
123
|
const templateEl = document.createElement("template");
|
|
141
124
|
|
|
125
|
+
// Decode HTML entities if the code is already encoded
|
|
126
|
+
let cleanCodeBlock = this.codeBlock;
|
|
127
|
+
if (this.isEncoded) {
|
|
128
|
+
// Create a temporary element to decode HTML entities
|
|
129
|
+
const tempElement = document.createElement("div");
|
|
130
|
+
tempElement.innerHTML = cleanCodeBlock;
|
|
131
|
+
cleanCodeBlock =
|
|
132
|
+
tempElement.textContent ||
|
|
133
|
+
tempElement.innerText ||
|
|
134
|
+
cleanCodeBlock;
|
|
135
|
+
}
|
|
136
|
+
|
|
142
137
|
// Replace any <var> markup with a temporary nonsense sentinel (but one that is very
|
|
143
|
-
// unlikely to affect
|
|
144
|
-
// still tokenize correctly. We want to italicize the "variables" ourselves after
|
|
138
|
+
// unlikely to affect Shiki's tokenization) so that Shiki will not strip them but does
|
|
139
|
+
// still tokenize correctly. We want to italicize the "variables" ourselves after Shiki
|
|
145
140
|
// does its own thing (W-11975205).
|
|
146
|
-
|
|
141
|
+
cleanCodeBlock = cleanCodeBlock.replace(
|
|
147
142
|
/<var.*?>(.+?)<\/var>/g,
|
|
148
143
|
"vvvvv$1vvvvv"
|
|
149
144
|
);
|
|
150
145
|
|
|
146
|
+
// For markup languages, preserve existing HTML comments but don't wrap the whole thing in comments
|
|
151
147
|
if (
|
|
152
148
|
!this.isEncoded &&
|
|
153
149
|
this.markupLangs.includes(this.selectedLanguage.id || "")
|
|
154
150
|
) {
|
|
155
|
-
// Temporarily replace HTML comment characters
|
|
156
|
-
cleanCodeBlock =
|
|
151
|
+
// Temporarily replace HTML comment characters to preserve them during highlighting
|
|
152
|
+
cleanCodeBlock = cleanCodeBlock.replace(
|
|
157
153
|
/<!--(.*?)-->/gs,
|
|
158
|
-
"@@$1
|
|
159
|
-
)
|
|
160
|
-
} else {
|
|
161
|
-
// If this is a non-encoded markup language, encode angle brackets that Prism would strip
|
|
162
|
-
cleanCodeBlock = this.isEncoded
|
|
163
|
-
? cleanCodeBlock
|
|
164
|
-
: cleanCodeBlock.replace(/</g, "<").replace(/>/g, ">");
|
|
154
|
+
"@@COMMENT_START@@$1@@COMMENT_END@@"
|
|
155
|
+
);
|
|
165
156
|
}
|
|
166
157
|
|
|
167
|
-
//
|
|
168
|
-
|
|
158
|
+
// Determine the language to use for highlighting
|
|
159
|
+
const languageForHighlighting = this.markupLangs.includes(
|
|
160
|
+
this.selectedLanguage.id || ""
|
|
161
|
+
)
|
|
162
|
+
? "html"
|
|
163
|
+
: this.selectedLanguage.id || "text";
|
|
169
164
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
codeEl.classList.add(
|
|
177
|
-
`language-${
|
|
178
|
-
this.markupLangs.includes(this.selectedLanguage.id || "")
|
|
179
|
-
? "markup"
|
|
180
|
-
: this.selectedLanguage.id
|
|
181
|
-
}`
|
|
165
|
+
try {
|
|
166
|
+
// Use Shiki to highlight the code with current theme
|
|
167
|
+
const highlightedHtml = await highlightCode(
|
|
168
|
+
cleanCodeBlock,
|
|
169
|
+
languageForHighlighting,
|
|
170
|
+
this.theme as "light" | "dark"
|
|
182
171
|
);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
this.language !== "text"
|
|
186
|
-
? // eslint-disable-next-line
|
|
187
|
-
(codeEl.innerHTML = codeHTML)
|
|
188
|
-
: (codeEl.textContent = this._codeBlock.trim());
|
|
189
|
-
// eslint-disable-next-line
|
|
190
|
-
codeBlockEl.innerHTML = "";
|
|
191
|
-
codeBlockEl.appendChild(codeEl);
|
|
192
|
-
prism.highlightAllUnder(codeBlockEl);
|
|
193
|
-
// Italicize anything marked as a "variable" by the docs team
|
|
172
|
+
|
|
173
|
+
const tempDiv = document.createElement("div");
|
|
194
174
|
// eslint-disable-next-line
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
175
|
+
tempDiv.innerHTML = highlightedHtml;
|
|
176
|
+
const preElement = tempDiv.querySelector("pre");
|
|
177
|
+
|
|
178
|
+
if (preElement) {
|
|
179
|
+
preElement.classList.add("codeblock");
|
|
180
|
+
|
|
181
|
+
// Italicize anything marked as a "variable" by the docs team
|
|
182
|
+
// eslint-disable-next-line
|
|
183
|
+
preElement.innerHTML = preElement.innerHTML.replace(
|
|
184
|
+
/vvvvv(.+?)vvvvv/g,
|
|
185
|
+
"<span class='token italic'>$1</span>"
|
|
186
|
+
);
|
|
187
|
+
// eslint-disable-next-line
|
|
188
|
+
templateEl.innerHTML = preElement.outerHTML;
|
|
189
|
+
} else {
|
|
190
|
+
// Fallback if Shiki fails
|
|
191
|
+
// eslint-disable-next-line
|
|
192
|
+
templateEl.innerHTML = `<pre class='codeblock'><code class='shiki'>${cleanCodeBlock}</code></pre>`;
|
|
193
|
+
}
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.error(
|
|
196
|
+
"Shiki highlighting failed, falling back to plain text:",
|
|
197
|
+
error
|
|
198
198
|
);
|
|
199
|
-
|
|
199
|
+
// Fallback to plain text
|
|
200
|
+
// eslint-disable-next-line
|
|
201
|
+
templateEl.innerHTML = `<pre class='codeblock'><code class='shiki'>${cleanCodeBlock}</code></pre>`;
|
|
202
|
+
}
|
|
200
203
|
|
|
201
204
|
if (divEl) {
|
|
202
205
|
// eslint-disable-next-line
|
|
203
206
|
divEl.innerHTML = "";
|
|
204
207
|
divEl.append(templateEl.content);
|
|
205
208
|
if (this.markupLangs.includes(this.selectedLanguage.id || "")) {
|
|
206
|
-
const res = this.template.querySelector(`code
|
|
209
|
+
const res = this.template.querySelector(`code`);
|
|
207
210
|
if (res) {
|
|
208
211
|
// Restore any temporarily replaced HTML comment characters
|
|
209
212
|
// eslint-disable-next-line
|
|
210
213
|
res.innerHTML = res.innerHTML.replace(
|
|
211
|
-
/@@(.*?)
|
|
214
|
+
/@@COMMENT_START@@(.*?)@@COMMENT_END@@/gs,
|
|
212
215
|
`<span class="token comment"><!--$1--></span>`
|
|
213
216
|
);
|
|
214
217
|
}
|
|
@@ -277,6 +280,13 @@ export default class CodeBlock extends LightningElement {
|
|
|
277
280
|
private toggleTheme = () => {
|
|
278
281
|
this.theme = this.theme === DARK ? LIGHT : DARK;
|
|
279
282
|
this.storeTheme();
|
|
283
|
+
// Re-render the code block with the new theme
|
|
284
|
+
this.formatCodeBlock().catch((error) => {
|
|
285
|
+
console.error(
|
|
286
|
+
"Failed to re-format code block after theme change:",
|
|
287
|
+
error
|
|
288
|
+
);
|
|
289
|
+
});
|
|
280
290
|
};
|
|
281
291
|
|
|
282
292
|
private storeTheme = () => {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* Custom prism.js stylesheet */
|
|
2
1
|
/* stylelint-disable selector-pseudo-element-no-unknown */
|
|
3
2
|
.dx-variant-block dx-button {
|
|
4
3
|
--dx-c-button-primary-color: var(--dx-g-gray-50);
|
|
@@ -21,8 +20,8 @@
|
|
|
21
20
|
--dx-c-button-inline-color-hover: var(--dx-g-hot-orange-vibrant-95);
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
pre[class*="
|
|
25
|
-
code[class*="
|
|
23
|
+
pre[class*="shiki"],
|
|
24
|
+
code[class*="shiki"] {
|
|
26
25
|
font-size: 14px;
|
|
27
26
|
text-shadow: none;
|
|
28
27
|
font-family: var(--dx-g-font-mono);
|
|
@@ -36,30 +35,30 @@ code[class*="language-"] {
|
|
|
36
35
|
hyphens: none;
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
pre[class*="
|
|
40
|
-
code[class*="
|
|
41
|
-
pre[class*="
|
|
42
|
-
code[class*="
|
|
38
|
+
pre[class*="shiki"]::selection,
|
|
39
|
+
code[class*="shiki"]::selection,
|
|
40
|
+
pre[class*="shiki"]::mozselection,
|
|
41
|
+
code[class*="shiki"]::mozselection {
|
|
43
42
|
text-shadow: none;
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
.dx-theme-dark code[class*="
|
|
45
|
+
.dx-theme-dark code[class*="shiki"] {
|
|
47
46
|
color: rgb(255 255 255);
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
.dx-theme-light code[class*="
|
|
49
|
+
.dx-theme-light code[class*="shiki"] {
|
|
51
50
|
color: var(--dx-g-gray-10);
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
.dx-theme-dark code[class*="
|
|
53
|
+
.dx-theme-dark code[class*="shiki"]::mozselection {
|
|
55
54
|
background: rgb(255 255 255);
|
|
56
55
|
}
|
|
57
56
|
|
|
58
|
-
.dx-theme-light code[class*="
|
|
57
|
+
.dx-theme-light code[class*="shiki"]::mozselection {
|
|
59
58
|
background: var(--dx-g-gray-95);
|
|
60
59
|
}
|
|
61
60
|
|
|
62
|
-
.dx-variant-card pre[class*="
|
|
61
|
+
.dx-variant-card pre[class*="shiki"] {
|
|
63
62
|
padding: 1em;
|
|
64
63
|
border-radius: 0 0 0.3em 0.3em;
|
|
65
64
|
overflow: auto;
|
|
@@ -67,12 +66,12 @@ code[class*="language-"]::mozselection {
|
|
|
67
66
|
white-space: pre;
|
|
68
67
|
}
|
|
69
68
|
|
|
70
|
-
.dx-variant-card :not(pre) > code[class*="
|
|
69
|
+
.dx-variant-card :not(pre) > code[class*="shiki"] {
|
|
71
70
|
padding: 0.1em 0.3em;
|
|
72
71
|
border-radius: 0.3em;
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
.dx-variant-block pre[class*="
|
|
74
|
+
.dx-variant-block pre[class*="shiki"] {
|
|
76
75
|
padding: 1em;
|
|
77
76
|
border-radius: 0.3em;
|
|
78
77
|
overflow: auto;
|
|
@@ -81,27 +80,27 @@ code[class*="language-"]::mozselection {
|
|
|
81
80
|
width: 94%;
|
|
82
81
|
}
|
|
83
82
|
|
|
84
|
-
.dx-variant-block :not(pre) > code[class*="
|
|
83
|
+
.dx-variant-block :not(pre) > code[class*="shiki"] {
|
|
85
84
|
padding: 0.1em 0.3em;
|
|
86
85
|
border-radius: 0.3em;
|
|
87
86
|
}
|
|
88
87
|
|
|
89
|
-
.dx-theme-dark pre[class*="
|
|
88
|
+
.dx-theme-dark pre[class*="shiki"] {
|
|
90
89
|
color: rgb(255 255 255);
|
|
91
90
|
background: var(--dx-g-blue-vibrant-10);
|
|
92
91
|
}
|
|
93
92
|
|
|
94
|
-
.dx-theme-dark :not(pre) > code[class*="
|
|
93
|
+
.dx-theme-dark :not(pre) > code[class*="shiki"] {
|
|
95
94
|
color: rgb(255 255 255);
|
|
96
95
|
background: var(--dx-g-blue-vibrant-10);
|
|
97
96
|
}
|
|
98
97
|
|
|
99
|
-
.dx-theme-light pre[class*="
|
|
98
|
+
.dx-theme-light pre[class*="shiki"] {
|
|
100
99
|
color: var(--dx-g-gray-10);
|
|
101
100
|
background: var(--dx-g-gray-95);
|
|
102
101
|
}
|
|
103
102
|
|
|
104
|
-
.dx-theme-light :not(pre) > code[class*="
|
|
103
|
+
.dx-theme-light :not(pre) > code[class*="shiki"] {
|
|
105
104
|
color: var(--dx-g-gray-10);
|
|
106
105
|
background: var(--dx-g-gray-95);
|
|
107
106
|
}
|
|
@@ -133,79 +132,12 @@ pre[data-line] {
|
|
|
133
132
|
position: relative;
|
|
134
133
|
}
|
|
135
134
|
|
|
136
|
-
pre[class*="
|
|
135
|
+
pre[class*="shiki"] > code[class*="shiki"] {
|
|
137
136
|
position: relative;
|
|
138
137
|
display: block;
|
|
139
138
|
z-index: 1;
|
|
140
139
|
}
|
|
141
140
|
|
|
142
|
-
.line-highlight {
|
|
143
|
-
position: absolute;
|
|
144
|
-
left: 0;
|
|
145
|
-
right: 0;
|
|
146
|
-
padding: inherit 0;
|
|
147
|
-
margin-top: 1em;
|
|
148
|
-
background: #1e2d50;
|
|
149
|
-
box-shadow: inset 5px 0 0 #0176d3;
|
|
150
|
-
z-index: 0;
|
|
151
|
-
pointer-events: none;
|
|
152
|
-
line-height: inherit;
|
|
153
|
-
white-space: pre;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
.line-numbers .line-highlight::before,
|
|
157
|
-
.line-numbers .line-highlight::after {
|
|
158
|
-
content: none;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
.line-numbers-rows > span::before {
|
|
162
|
-
content: counter(linenumber);
|
|
163
|
-
color: var(--dx-g-gray-50);
|
|
164
|
-
display: block;
|
|
165
|
-
padding-right: 0.4em;
|
|
166
|
-
text-align: right;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
pre[id].linkable-line-numbers span.line-numbers-rows {
|
|
170
|
-
pointer-events: all;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
pre[id].linkable-line-numbers span.line-numbers-rows > span::before {
|
|
174
|
-
cursor: pointer;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
pre[id].linkable-line-numbers span.line-numbers-rows > span:hover::before {
|
|
178
|
-
background-color: rgb(128 128 128 / 20%);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
pre[class*="language-"].line-numbers {
|
|
182
|
-
position: relative;
|
|
183
|
-
padding-left: 3.8em;
|
|
184
|
-
counter-reset: linenumber;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
pre[class*="language-"].line-numbers > code {
|
|
188
|
-
position: relative;
|
|
189
|
-
white-space: inherit;
|
|
190
|
-
width: 1px;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
.line-numbers .line-numbers-rows {
|
|
194
|
-
position: absolute;
|
|
195
|
-
pointer-events: none;
|
|
196
|
-
top: 0;
|
|
197
|
-
font-size: 100%;
|
|
198
|
-
left: -3.8em;
|
|
199
|
-
width: 3em; /* works for line-numbers below 1000 lines */
|
|
200
|
-
letter-spacing: -1px;
|
|
201
|
-
user-select: none;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
.line-numbers-rows > span {
|
|
205
|
-
display: block;
|
|
206
|
-
counter-increment: linenumber;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
141
|
.dx-variant-block.code-toolbar {
|
|
210
142
|
display: flex;
|
|
211
143
|
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// Mock for shiki module
|
|
2
|
+
export const createHighlighter = jest.fn().mockImplementation(() => {
|
|
3
|
+
return Promise.resolve({
|
|
4
|
+
codeToHtml: jest.fn().mockImplementation((code, options) => {
|
|
5
|
+
// Preserve the original code content and add variable elements if present
|
|
6
|
+
let htmlContent = code;
|
|
7
|
+
|
|
8
|
+
// Check for <var> elements in the code and preserve them
|
|
9
|
+
if (code.includes("<var>")) {
|
|
10
|
+
// Replace <var> elements with tokenized spans
|
|
11
|
+
htmlContent = code.replace(
|
|
12
|
+
/<var>(.*?)<\/var>/g,
|
|
13
|
+
(match, content) =>
|
|
14
|
+
`<span class="token variable"><var>${content}</var></span>`
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Add test content for specific test cases
|
|
19
|
+
if (code.includes("Salesforce Functions")) {
|
|
20
|
+
htmlContent = "Connected to Salesforce Functions";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return `<pre class="shiki ${
|
|
24
|
+
options?.theme || "light"
|
|
25
|
+
}"><code>${htmlContent}</code></pre>`;
|
|
26
|
+
}),
|
|
27
|
+
getLoadedLanguages: jest
|
|
28
|
+
.fn()
|
|
29
|
+
.mockReturnValue([
|
|
30
|
+
"javascript",
|
|
31
|
+
"typescript",
|
|
32
|
+
"html",
|
|
33
|
+
"css",
|
|
34
|
+
"apex",
|
|
35
|
+
"text",
|
|
36
|
+
"handlebars"
|
|
37
|
+
])
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export type Highlighter = {
|
|
42
|
+
codeToHtml: (code: string, options: any) => string;
|
|
43
|
+
getLoadedLanguages: () => string[];
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type BundledLanguage = string;
|
|
47
|
+
export type BundledTheme = string;
|
|
48
|
+
|
|
49
|
+
export const codeToHast = jest.fn();
|
|
50
|
+
export const codeToHtml = jest.fn();
|
|
51
|
+
export const codeToTokens = jest.fn();
|
|
52
|
+
export const codeToTokensBase = jest.fn();
|
|
53
|
+
export const codeToTokensWithThemes = jest.fn();
|
|
54
|
+
export const getLastGrammarState = jest.fn();
|
|
55
|
+
export const getSingletonHighlighter = jest.fn();
|
|
56
|
+
|
|
57
|
+
// Mock for shiki/core exports
|
|
58
|
+
export const createHighlighterCore = jest.fn().mockImplementation(() => {
|
|
59
|
+
return Promise.resolve({
|
|
60
|
+
codeToHtml: jest.fn().mockImplementation((code, options) => {
|
|
61
|
+
// Preserve the original code content and add variable elements if present
|
|
62
|
+
let htmlContent = code;
|
|
63
|
+
|
|
64
|
+
// Check for <var> elements in the code and preserve them
|
|
65
|
+
if (code.includes("<var>")) {
|
|
66
|
+
// Replace <var> elements with tokenized spans
|
|
67
|
+
htmlContent = code.replace(
|
|
68
|
+
/<var>(.*?)<\/var>/g,
|
|
69
|
+
(match, content) =>
|
|
70
|
+
`<span class="token variable"><var>${content}</var></span>`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Add test content for specific test cases
|
|
75
|
+
if (code.includes("Salesforce Functions")) {
|
|
76
|
+
htmlContent = "Connected to Salesforce Functions";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return `<pre class="shiki ${
|
|
80
|
+
options?.theme || "light"
|
|
81
|
+
}"><code>${htmlContent}</code></pre>`;
|
|
82
|
+
}),
|
|
83
|
+
getLoadedLanguages: jest
|
|
84
|
+
.fn()
|
|
85
|
+
.mockReturnValue([
|
|
86
|
+
"javascript",
|
|
87
|
+
"typescript",
|
|
88
|
+
"html",
|
|
89
|
+
"css",
|
|
90
|
+
"apex",
|
|
91
|
+
"text",
|
|
92
|
+
"handlebars"
|
|
93
|
+
]),
|
|
94
|
+
loadLanguage: jest.fn().mockResolvedValue(undefined)
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
export type HighlighterCore = {
|
|
99
|
+
codeToHtml: (code: string, options: any) => string;
|
|
100
|
+
getLoadedLanguages: () => string[];
|
|
101
|
+
loadLanguage: (lang: any) => Promise<void>;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// Mock for shiki/engine/oniguruma
|
|
105
|
+
export const createOnigurumaEngine = jest.fn().mockImplementation(() => {
|
|
106
|
+
return Promise.resolve({});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Mock for shiki/wasm - just return a promise that resolves to a buffer
|
|
110
|
+
export default Promise.resolve(new ArrayBuffer(0));
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Mock for @shikijs/* packages
|
|
2
|
+
|
|
3
|
+
// Mock language modules - return a grammar object
|
|
4
|
+
const mockLanguage = {
|
|
5
|
+
name: "mock-language",
|
|
6
|
+
scopeName: "source.mock",
|
|
7
|
+
patterns: []
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// Mock theme modules - return a theme object
|
|
11
|
+
const mockTheme = {
|
|
12
|
+
name: "mock-theme",
|
|
13
|
+
type: "light",
|
|
14
|
+
colors: {},
|
|
15
|
+
tokenColors: []
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Default export for all @shikijs modules
|
|
19
|
+
export default mockLanguage;
|
|
20
|
+
|
|
21
|
+
// Also export as named export for themes
|
|
22
|
+
export const theme = mockTheme;
|
|
23
|
+
export const lang = mockLanguage;
|