@salesforcedevs/dx-components 1.30.0 → 1.30.1-node22-2
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/lwc.config.json +4 -1
- package/package.json +7 -3
- package/src/modules/dx/emptyState/emptyState.html +1 -1
- package/src/modules/dx/emptyState/emptyState.ts +2 -2
- package/src/modules/dx/error/error.css +3 -3
- package/src/modules/dx/errorFallback/errorFallback.html +1 -1
- package/src/modules/dx/feature/feature.css +2 -2
- package/src/modules/dx/feature/feature.html +1 -1
- package/src/modules/dx/featuredContentHeader/featuredContentHeader.css +5 -5
- package/src/modules/dx/featuredContentHeader/svgs.ts +2 -2
- package/src/modules/dx/footer/footer.css +4 -4
- package/src/modules/dx/footer/footer.html +1 -1
- package/src/modules/dx/footer/footer.ts +1 -1
- package/src/modules/dx/input/input.ts +1 -1
- package/src/modules/dx/logo/logo.ts +1 -1
- package/src/modules/dx/searchResults/resultsTemplate.js +1 -1
- package/src/modules/dx/searchResults/searchResults.css +4 -4
- package/src/modules/dx/sectionBanner/sectionBanner.html +1 -1
- package/src/modules/dx/sidebar/sidebar.html +1 -1
- package/src/modules/dx/treeItem/treeItem.html +1 -1
- package/src/modules/dxUtils/shiki/__mocks__/shiki.ts +2 -1
- package/src/modules/dxUtils/shiki/__mocks__/shikijs.ts +6 -0
- package/src/modules/dxUtils/shiki/shiki.ts +26 -176
- package/src/modules/dxUtils/shikiCore/shikiCore.ts +188 -0
- package/src/modules/dxUtils/shikiStatic/shikiStatic.html +3 -0
- package/src/modules/dxUtils/shikiStatic/shikiStatic.ts +46 -0
package/lwc.config.json
CHANGED
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforcedevs/dx-components",
|
|
3
|
-
"version": "1.30.
|
|
3
|
+
"version": "1.30.1-node22-2",
|
|
4
4
|
"description": "DX Lightning web components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
7
|
-
"node": "
|
|
7
|
+
"node": ">=22.0.0"
|
|
8
|
+
},
|
|
9
|
+
"volta": {
|
|
10
|
+
"node": "22.22.0",
|
|
11
|
+
"yarn": "1.22.22"
|
|
8
12
|
},
|
|
9
13
|
"publishConfig": {
|
|
10
14
|
"access": "public"
|
|
@@ -44,5 +48,5 @@
|
|
|
44
48
|
"luxon": "3.4.4",
|
|
45
49
|
"msw": "^2.12.4"
|
|
46
50
|
},
|
|
47
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "db460ac1fb9b1f752d0c129dfe19012c8a085867"
|
|
48
52
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<img class={imageClassName} src={imageAssetPath} alt={imageAlt} />
|
|
4
4
|
<img
|
|
5
5
|
class="image-alt-small"
|
|
6
|
-
src="https://
|
|
6
|
+
src="https://developer.salesforce.com/ns-assets/images/binary-cloud-circle-small.svg"
|
|
7
7
|
alt="Cloud with binary code floating above"
|
|
8
8
|
lwc:if={altVariant}
|
|
9
9
|
/>
|
|
@@ -60,10 +60,10 @@ export default class EmptyState extends LightningElement {
|
|
|
60
60
|
|
|
61
61
|
get imageAssetPath() {
|
|
62
62
|
return this.variant === "base"
|
|
63
|
-
? `https://
|
|
63
|
+
? `https://developer.salesforce.com/ns-assets/images/docs-empty-state${
|
|
64
64
|
this.size === "small" ? "-small" : ""
|
|
65
65
|
}.svg`
|
|
66
|
-
: `https://
|
|
66
|
+
: `https://developer.salesforce.com/ns-assets/images/binary-cloud-circle${
|
|
67
67
|
this.size === "small" ? "-small" : ""
|
|
68
68
|
}.svg`;
|
|
69
69
|
}
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
.error_container {
|
|
10
10
|
background-color: #3a49da;
|
|
11
|
-
background-image: url("https://
|
|
12
|
-
url("https://
|
|
13
|
-
url("https://
|
|
11
|
+
background-image: url("https://developer.salesforce.com/ns-assets/images/bottom-right.svg"),
|
|
12
|
+
url("https://developer.salesforce.com/ns-assets/images/lower-left.svg"),
|
|
13
|
+
url("https://developer.salesforce.com/ns-assets/images/top-right.svg");
|
|
14
14
|
background-position: right bottom, left 90%, right top;
|
|
15
15
|
background-repeat: no-repeat;
|
|
16
16
|
padding: var(--dx-g-spacing-3xl) calc(var(--dx-g-spacing-3xl) + 20px) 130px
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
:host {
|
|
5
5
|
--dx-c-feature-img-box-shadow: 0 6px 30px 0 rgb(0 20 45 / 40%);
|
|
6
|
-
--dx-c-feature-description-left-img-src: url("https://
|
|
6
|
+
--dx-c-feature-description-left-img-src: url("https://developer.salesforce.com/ns-assets/images/feature-backdrop1.svg");
|
|
7
7
|
--dx-c-feature-description-max-width: 31.75rem;
|
|
8
8
|
--dx-c-feature-img-margin-left: auto;
|
|
9
9
|
--dx-c-feature-img-container-padding: 4rem;
|
|
@@ -83,7 +83,7 @@ section {
|
|
|
83
83
|
|
|
84
84
|
.description-right .image {
|
|
85
85
|
margin-right: auto;
|
|
86
|
-
background-image: url("https://
|
|
86
|
+
background-image: url("https://developer.salesforce.com/ns-assets/images/feature-backdrop2.svg");
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
.image-display-container {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
<div if:true={isDisplay} class="image-display-container">
|
|
22
22
|
<img
|
|
23
23
|
class="image-display"
|
|
24
|
-
src="https://
|
|
24
|
+
src="https://developer.salesforce.com/ns-assets/images/featured-demo-art-blank.svg"
|
|
25
25
|
alt={header}
|
|
26
26
|
/>
|
|
27
27
|
<div class="image-container">
|
|
@@ -221,8 +221,8 @@
|
|
|
221
221
|
|
|
222
222
|
.custom-bg-trial::after {
|
|
223
223
|
content: "";
|
|
224
|
-
background-image: url("https://
|
|
225
|
-
url("https://
|
|
224
|
+
background-image: url("https://developer.salesforce.com/ns-assets/images/trial-left.svg"),
|
|
225
|
+
url("https://developer.salesforce.com/ns-assets/images/trial-right.svg");
|
|
226
226
|
background-position: var(--dx-g-page-padding-horizontal) 50px,
|
|
227
227
|
right 15px top;
|
|
228
228
|
background-repeat: no-repeat;
|
|
@@ -235,7 +235,7 @@
|
|
|
235
235
|
|
|
236
236
|
@media screen and (max-width: 1024px) {
|
|
237
237
|
.custom-bg-trial::after {
|
|
238
|
-
background-image: url("https://
|
|
238
|
+
background-image: url("https://developer.salesforce.com/ns-assets/images/trial-left.svg");
|
|
239
239
|
background-position: 48px 30px;
|
|
240
240
|
background-size: contain;
|
|
241
241
|
}
|
|
@@ -243,7 +243,7 @@
|
|
|
243
243
|
|
|
244
244
|
.custom-bg-big-moon::after {
|
|
245
245
|
content: "";
|
|
246
|
-
background-image: url("https://
|
|
246
|
+
background-image: url("https://developer.salesforce.com/ns-assets/images/big-moon.svg");
|
|
247
247
|
background-position: top right;
|
|
248
248
|
background-repeat: no-repeat;
|
|
249
249
|
position: absolute;
|
|
@@ -258,7 +258,7 @@
|
|
|
258
258
|
justify-content: center;
|
|
259
259
|
align-items: center;
|
|
260
260
|
position: absolute;
|
|
261
|
-
background-image: url("https://
|
|
261
|
+
background-image: url("https://developer.salesforce.com/ns-assets/images/blue-circle.svg");
|
|
262
262
|
top: 110px;
|
|
263
263
|
right: 230px;
|
|
264
264
|
left: unset;
|
|
@@ -6,10 +6,10 @@ const treesMobile =
|
|
|
6
6
|
|
|
7
7
|
// These codey-* ones are a bit of a hack for now: we were only given a PNG and limited time, so we're wrapping the PNG in an SVG.
|
|
8
8
|
const codeyDesktop =
|
|
9
|
-
'<svg class="codey-desktop" width="381" height="337" viewBox="0 0 381 337" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><image width="381" height="337" xlink:href="https://
|
|
9
|
+
'<svg class="codey-desktop" width="381" height="337" viewBox="0 0 381 337" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><image width="381" height="337" xlink:href="https://developer.salesforce.com/ns-assets/images/podcast-bear.png" />';
|
|
10
10
|
|
|
11
11
|
const codeyMobile =
|
|
12
|
-
'<svg class="codey-mobile" width="381" height="337" viewBox="0 0 381 337" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><image width="381" height="337" xlink:href="https://
|
|
12
|
+
'<svg class="codey-mobile" width="381" height="337" viewBox="0 0 381 337" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><image width="381" height="337" xlink:href="https://developer.salesforce.com/ns-assets/images/podcast-bear.png" />';
|
|
13
13
|
|
|
14
14
|
const moonDesktop =
|
|
15
15
|
'<svg width="1221" height="507" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M745.819 45.482c0 24.567-19.915 44.482-44.482 44.482s-44.483-19.915-44.483-44.482C656.854 20.916 676.77 1 701.337 1c24.567 0 44.482 19.916 44.482 44.482"/><path d="M745.819 45.482c0 24.567-19.915 44.482-44.482 44.482s-44.483-19.915-44.483-44.482C656.854 20.916 676.77 1 701.337 1c24.567 0 44.482 19.916 44.482 44.482Z" stroke="#90D0FE" stroke-width="2"/><path d="M476.154 420.627a4.095 4.095 0 1 1-8.191 0 4.095 4.095 0 1 1 8.19 0ZM99.154 150.627a4.095 4.095 0 1 1-8.191 0 4.095 4.095 0 1 1 8.19 0ZM1210.142 97.587l-1.518 4.1a1.063 1.063 0 0 1-.631.633l-4.102 1.518c-.933.346-.933 1.664 0 2.009l4.102 1.517c.293.109.523.34.63.633l1.519 4.102c.346.93 1.664.93 2.009 0l1.517-4.102c.109-.293.34-.524.633-.633l4.102-1.517c.932-.345.932-1.663 0-2.01l-4.102-1.517a1.068 1.068 0 0 1-.633-.632l-1.517-4.101c-.345-.933-1.663-.933-2.01 0ZM8.142 490.372l-1.518 4.1a1.067 1.067 0 0 1-.632.633l-4.1 1.518c-.934.345-.934 1.664 0 2.009l4.1 1.517c.293.109.524.34.632.633l1.518 4.1c.345.933 1.664.933 2.01 0l1.516-4.1c.11-.293.34-.524.633-.633l4.101-1.517c.932-.345.932-1.664 0-2.01l-4.1-1.517a1.071 1.071 0 0 1-.634-.632l-1.517-4.101c-.345-.933-1.664-.933-2.009 0ZM127.142 115.587l-1.518 4.1a1.064 1.064 0 0 1-.632.633l-4.1 1.518c-.934.346-.934 1.664 0 2.009l4.1 1.517c.293.109.524.34.632.633l1.518 4.102c.345.93 1.664.93 2.01 0l1.516-4.102c.11-.293.34-.524.633-.633l4.101-1.517c.932-.345.932-1.663 0-2.01l-4.1-1.517a1.068 1.068 0 0 1-.634-.632l-1.517-4.101c-.345-.933-1.664-.933-2.009 0ZM909.009 306.108c-5.999-11.612-9.387-24.793-9.387-38.765 0-11.403 2.257-22.279 6.348-32.206M1067.92 255.215c.568 3.96.862 8.01.862 12.129 0 46.713-37.867 84.58-84.58 84.58-28.474 0-53.664-14.071-68.99-35.64M911.555 224.004c14.768-24.701 41.776-41.24 72.647-41.24 38.302 0 70.658 25.459 81.068 60.378M1055.511 147.787l-3.452 9.329a2.439 2.439 0 0 1-1.44 1.44l-9.329 3.452c-2.121.784-2.121 3.784 0 4.569l9.329 3.452a2.436 2.436 0 0 1 1.44 1.44l3.452 9.329c.785 2.12 3.785 2.12 4.569 0l3.452-9.33a2.441 2.441 0 0 1 1.44-1.44l9.329-3.451c2.121-.785 2.121-3.785 0-4.57l-9.329-3.451a2.444 2.444 0 0 1-1.44-1.44l-3.452-9.33c-.784-2.12-3.784-2.12-4.569 0ZM919.251 376.385c0 5.69-4.614 10.304-10.306 10.304-5.69 0-10.305-4.613-10.305-10.305 0-5.692 4.614-10.306 10.305-10.306 5.692 0 10.306 4.615 10.306 10.307Z" stroke="#90D0FE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M984.116 224.502a5.027 5.027 0 1 1-10.054 0 5.027 5.027 0 0 1 10.054 0" fill="#90D0FE"/><path stroke="#90D0FE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M1046.716 254.771h29.772M1087.929 254.771h7.089M902.279 225.33h23.242M870.108 225.33h10.053"/><path d="M893.055 225.33a2.01 2.01 0 1 1-4.021 0 2.01 2.01 0 0 1 4.02 0" fill="#90D0FE"/><path stroke="#90D0FE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M893.425 315.627h31.409"/><path d="M936.898 315.627a2.011 2.011 0 1 1-4.023 0 2.011 2.011 0 0 1 4.023 0" fill="#90D0FE"/><path stroke="#90D0FE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M1013.52 292.398v-16.036M1021.537 284.382l-16.051.002"/></g></svg>';
|
|
@@ -113,7 +113,7 @@ footer.signup-variant-no-signup {
|
|
|
113
113
|
height: 112px;
|
|
114
114
|
width: 110px;
|
|
115
115
|
margin-right: var(--dx-g-spacing-lg);
|
|
116
|
-
background-image: url("https://
|
|
116
|
+
background-image: url("https://developer.salesforce.com/ns-assets/images/footer-graphic-trees.svg");
|
|
117
117
|
filter: var(--dx-g-svg-filter);
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -121,7 +121,7 @@ footer.signup-variant-no-signup {
|
|
|
121
121
|
height: 96px;
|
|
122
122
|
width: 220px;
|
|
123
123
|
margin-right: var(--dx-g-spacing-lg);
|
|
124
|
-
background-image: url("https://
|
|
124
|
+
background-image: url("https://developer.salesforce.com/ns-assets/images/footer-graphic-mountains-2.svg");
|
|
125
125
|
filter: var(--dx-g-svg-filter);
|
|
126
126
|
}
|
|
127
127
|
|
|
@@ -132,7 +132,7 @@ footer.signup-variant-no-signup {
|
|
|
132
132
|
bottom: 0;
|
|
133
133
|
height: 56px;
|
|
134
134
|
width: 100px;
|
|
135
|
-
background-image: url("https://
|
|
135
|
+
background-image: url("https://developer.salesforce.com/ns-assets/images/footer-graphic-mountains-small-2.svg");
|
|
136
136
|
filter: var(--dx-g-svg-filter);
|
|
137
137
|
}
|
|
138
138
|
|
|
@@ -140,7 +140,7 @@ footer.signup-variant-no-signup {
|
|
|
140
140
|
height: 66px;
|
|
141
141
|
width: 52px;
|
|
142
142
|
margin-left: var(--dx-g-spacing-lg);
|
|
143
|
-
background-image: url("https://
|
|
143
|
+
background-image: url("https://developer.salesforce.com/ns-assets/images/footer-graphic-trees-small.svg");
|
|
144
144
|
filter: var(--dx-g-svg-filter);
|
|
145
145
|
}
|
|
146
146
|
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
>
|
|
57
57
|
<a class="logo" href="/">
|
|
58
58
|
<img
|
|
59
|
-
src="https://
|
|
59
|
+
src="https://developer.salesforce.com/ns-assets/images/salesforce-logo-corporate.svg"
|
|
60
60
|
alt="Salesforce logo"
|
|
61
61
|
/>
|
|
62
62
|
</a>
|
|
@@ -288,7 +288,7 @@ function augmentWithNonMFEFooterFunctionality(FooterClass: typeof Footer) {
|
|
|
288
288
|
link.href = "#";
|
|
289
289
|
link.onclick = this.openOneTrustInfoDisplay;
|
|
290
290
|
} else if (item.title === "Your Privacy Choices") {
|
|
291
|
-
link.img = "https://
|
|
291
|
+
link.img = "https://developer.salesforce.com/ns-assets/images/privacyoptions.svg";
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
return link;
|
|
@@ -195,7 +195,7 @@ export default class Input extends LightningElement {
|
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
private get shortcutImgSrc() {
|
|
198
|
-
return `https://
|
|
198
|
+
return `https://developer.salesforce.com/ns-assets/images/${this.commandKey}.svg`;
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
private get shortcutImgAlt() {
|
|
@@ -3,7 +3,7 @@ import { LightningElement, api } from "lwc";
|
|
|
3
3
|
export default class Logo extends LightningElement {
|
|
4
4
|
@api href: string = "/";
|
|
5
5
|
@api imgSrc: string =
|
|
6
|
-
"https://
|
|
6
|
+
"https://developer.salesforce.com/ns-assets/images/salesforce-cloud.svg";
|
|
7
7
|
@api imgAlt: string = "Salesforce logo";
|
|
8
8
|
@api label!: string;
|
|
9
9
|
}
|
|
@@ -9,7 +9,7 @@ export default html`
|
|
|
9
9
|
<div class="coveo-show-if-no-results">
|
|
10
10
|
<div class="no-results">
|
|
11
11
|
<img
|
|
12
|
-
src="https://
|
|
12
|
+
src="https://developer.salesforce.com/ns-assets/images/binary-cloud-circle-small.svg"
|
|
13
13
|
alt="purple cloud with floating binary numbers above"
|
|
14
14
|
/>
|
|
15
15
|
<div class="no-results-info">
|
|
@@ -311,7 +311,7 @@ li.coveo-dynamic-facet-breadcrumb-value-list-item {
|
|
|
311
311
|
|
|
312
312
|
.dx-search-header {
|
|
313
313
|
padding: var(--dx-g-spacing-xl);
|
|
314
|
-
background: url("https://
|
|
314
|
+
background: url("https://developer.salesforce.com/ns-assets/images/binary-cloud-trees.svg")
|
|
315
315
|
no-repeat 100% 0,
|
|
316
316
|
linear-gradient(
|
|
317
317
|
77deg,
|
|
@@ -352,7 +352,7 @@ li.coveo-dynamic-facet-breadcrumb-value-list-item {
|
|
|
352
352
|
|
|
353
353
|
@media (min-width: 928px) and (max-width: 1024px) {
|
|
354
354
|
.dx-search-header {
|
|
355
|
-
background: url("https://
|
|
355
|
+
background: url("https://developer.salesforce.com/ns-assets/images/binary-cloud-trees.svg")
|
|
356
356
|
no-repeat 200% 0,
|
|
357
357
|
linear-gradient(
|
|
358
358
|
77deg,
|
|
@@ -380,7 +380,7 @@ li.coveo-dynamic-facet-breadcrumb-value-list-item {
|
|
|
380
380
|
|
|
381
381
|
@media (min-width: 768px) and (max-width: 928px) {
|
|
382
382
|
.dx-search-header {
|
|
383
|
-
background: url("https://
|
|
383
|
+
background: url("https://developer.salesforce.com/ns-assets/images/binary-trees.svg")
|
|
384
384
|
no-repeat 90% 50%,
|
|
385
385
|
linear-gradient(
|
|
386
386
|
77deg,
|
|
@@ -392,7 +392,7 @@ li.coveo-dynamic-facet-breadcrumb-value-list-item {
|
|
|
392
392
|
|
|
393
393
|
@media (max-width: 768px) {
|
|
394
394
|
.dx-search-header {
|
|
395
|
-
background: url("https://
|
|
395
|
+
background: url("https://developer.salesforce.com/ns-assets/images/binary.svg")
|
|
396
396
|
no-repeat 90% 50%,
|
|
397
397
|
linear-gradient(
|
|
398
398
|
77deg,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<img
|
|
4
4
|
if:false={hideTopGraphic}
|
|
5
5
|
class="graphic"
|
|
6
|
-
src="https://
|
|
6
|
+
src="https://developer.salesforce.com/ns-assets/images/dx-section-banner-graphic-1.svg"
|
|
7
7
|
alt=""
|
|
8
8
|
/>
|
|
9
9
|
<div class="content">
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
<img
|
|
70
70
|
lwc:if={isSearchLoading}
|
|
71
71
|
class="loading-skeleton padding-horizontal"
|
|
72
|
-
src="https://
|
|
72
|
+
src="https://developer.salesforce.com/ns-assets/images/sidebar-loading.svg"
|
|
73
73
|
alt="loading"
|
|
74
74
|
/>
|
|
75
75
|
<template
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<img
|
|
17
17
|
if:true={showChildrenLoading}
|
|
18
18
|
class="tree-children-loading"
|
|
19
|
-
src="https://
|
|
19
|
+
src="https://developer.salesforce.com/ns-assets/images/sidebar-item-loading.svg"
|
|
20
20
|
alt="childrenLoading"
|
|
21
21
|
/>
|
|
22
22
|
<template if:true={showChildren} tabindex="0">
|
|
@@ -21,3 +21,9 @@ export default mockLanguage;
|
|
|
21
21
|
// Also export as named export for themes
|
|
22
22
|
export const theme = mockTheme;
|
|
23
23
|
export const lang = mockLanguage;
|
|
24
|
+
|
|
25
|
+
// Mock for @shikijs/colorized-brackets
|
|
26
|
+
export const transformerColorizedBrackets = () => ({
|
|
27
|
+
name: "colorized-brackets",
|
|
28
|
+
preprocess: (code: string) => code
|
|
29
|
+
});
|
|
@@ -1,5 +1,17 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { HighlighterCore } from "shiki";
|
|
2
|
+
import {
|
|
3
|
+
createShikiState,
|
|
4
|
+
initializeHighlighter,
|
|
5
|
+
highlightCodeWithShiki,
|
|
6
|
+
escapeHtml as coreEscapeHtml,
|
|
7
|
+
ShikiState
|
|
8
|
+
} from "dxUtils/shikiCore";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Dynamic loading version of Shiki.
|
|
12
|
+
* Uses dynamic import() for code splitting - shiki is lazy loaded on first use.
|
|
13
|
+
* Note: May not work with SSG. Use dxUtils/shikiStatic for SSG compatibility.
|
|
14
|
+
*/
|
|
3
15
|
|
|
4
16
|
let shikiModulePromise: Promise<typeof import("shiki")> | null = null;
|
|
5
17
|
let bracketsModulePromise: Promise<
|
|
@@ -14,156 +26,13 @@ async function getBrackets() {
|
|
|
14
26
|
return (bracketsModulePromise ??= import("@shikijs/colorized-brackets"));
|
|
15
27
|
}
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
highlighter: HighlighterCore | null;
|
|
19
|
-
initialized: boolean;
|
|
20
|
-
initPromise: Promise<HighlighterCore> | null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const shikiInstance: ShikiSingleton = {
|
|
24
|
-
highlighter: null,
|
|
25
|
-
initialized: false,
|
|
26
|
-
initPromise: null
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
// Theme mapping for light/dark modes
|
|
30
|
-
const THEME_MAP: Record<string, BundledTheme> = {
|
|
31
|
-
light: "light-plus",
|
|
32
|
-
dark: "material-theme-darker"
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const THEME_MAP_COLOR_REPLACEMENTS: Record<
|
|
36
|
-
string,
|
|
37
|
-
{ colorReplacements: Record<string, string> }
|
|
38
|
-
> = {
|
|
39
|
-
light: {
|
|
40
|
-
colorReplacements: {}
|
|
41
|
-
},
|
|
42
|
-
dark: {
|
|
43
|
-
colorReplacements: {
|
|
44
|
-
"#545454": "#8A8A8A" // Replace comment color for WCAG 2.1 compliance
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// Language mapping for custom languages to supported ones
|
|
50
|
-
const LANGUAGE_MAP: Record<string, BundledLanguage> = {
|
|
51
|
-
ssjs: "javascript", // Server-Side JavaScript
|
|
52
|
-
gtl: "handlebars", // Guide Template Language similar to Handlebars
|
|
53
|
-
lwc: "jsx",
|
|
54
|
-
sql_docs_template: "sql", // Custom SQL variant
|
|
55
|
-
visualforce: "html", // Visualforce uses HTML-like syntax
|
|
56
|
-
js: "javascript",
|
|
57
|
-
ts: "typescript",
|
|
58
|
-
yml: "yaml",
|
|
59
|
-
md: "markdown",
|
|
60
|
-
sh: "bash"
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// Core languages loaded eagerly (keep minimal; load others on demand)
|
|
64
|
-
const CORE_LANGUAGES: BundledLanguage[] = [
|
|
65
|
-
"apex",
|
|
66
|
-
"javascript",
|
|
67
|
-
"html",
|
|
68
|
-
"css",
|
|
69
|
-
"json",
|
|
70
|
-
"sql",
|
|
71
|
-
"bash",
|
|
72
|
-
"xml",
|
|
73
|
-
"graphql",
|
|
74
|
-
"jsx",
|
|
75
|
-
getCustomLanguageGrammars().ampscript
|
|
76
|
-
];
|
|
29
|
+
const shikiState: ShikiState = createShikiState();
|
|
77
30
|
|
|
78
|
-
// Non-critical languages that can be loaded asynchronously when needed
|
|
79
|
-
const OPTIONAL_LANGUAGES: Record<string, any> = {
|
|
80
|
-
// @ts-ignore
|
|
81
|
-
typescript: "typescript",
|
|
82
|
-
// @ts-ignore
|
|
83
|
-
markdown: "markdown",
|
|
84
|
-
// @ts-ignore
|
|
85
|
-
python: "python",
|
|
86
|
-
// @ts-ignore
|
|
87
|
-
java: "java",
|
|
88
|
-
// @ts-ignore
|
|
89
|
-
yaml: "yaml",
|
|
90
|
-
// @ts-ignore
|
|
91
|
-
php: "php",
|
|
92
|
-
// @ts-ignore
|
|
93
|
-
swift: "swift",
|
|
94
|
-
// @ts-ignore
|
|
95
|
-
kotlin: "kotlin",
|
|
96
|
-
// @ts-ignore
|
|
97
|
-
handlebars: "handlebars",
|
|
98
|
-
// @ts-ignore
|
|
99
|
-
dataweave: getCustomLanguageGrammars().dataweave,
|
|
100
|
-
// @ts-ignore
|
|
101
|
-
agentscript: getCustomLanguageGrammars().agentscript
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
// Initialize Shiki highlighter (lazy-load module and keep initial set minimal)
|
|
105
31
|
async function initializeShiki(): Promise<HighlighterCore> {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (shikiInstance.initPromise) {
|
|
111
|
-
return shikiInstance.initPromise;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Assign promise IMMEDIATELY before any async work to prevent race conditions
|
|
115
|
-
shikiInstance.initPromise = (async () => {
|
|
116
|
-
const shiki = await getShiki();
|
|
117
|
-
const highlighter = await shiki.createHighlighter({
|
|
118
|
-
themes: ["light-plus", "material-theme-darker"],
|
|
119
|
-
langs: CORE_LANGUAGES
|
|
120
|
-
});
|
|
121
|
-
shikiInstance.highlighter = highlighter;
|
|
122
|
-
shikiInstance.initialized = true;
|
|
123
|
-
return highlighter;
|
|
124
|
-
})();
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
return await shikiInstance.initPromise;
|
|
128
|
-
} catch (error) {
|
|
129
|
-
console.error("Failed to initialize Shiki:", error);
|
|
130
|
-
shikiInstance.initPromise = null;
|
|
131
|
-
throw error;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Async function to load additional languages when needed
|
|
136
|
-
async function loadLanguageIfNeeded(
|
|
137
|
-
highlighter: HighlighterCore,
|
|
138
|
-
language: string
|
|
139
|
-
): Promise<void> {
|
|
140
|
-
const loadedLanguages = highlighter.getLoadedLanguages();
|
|
141
|
-
|
|
142
|
-
if (!loadedLanguages.includes(language as BundledLanguage)) {
|
|
143
|
-
// Check if it's an optional language that needs to be loaded
|
|
144
|
-
const languageLoader = OPTIONAL_LANGUAGES[language];
|
|
145
|
-
|
|
146
|
-
if (languageLoader) {
|
|
147
|
-
try {
|
|
148
|
-
await highlighter.loadLanguage(languageLoader);
|
|
149
|
-
} catch (error) {
|
|
150
|
-
console.warn(
|
|
151
|
-
`Failed to load optional language ${language}:`,
|
|
152
|
-
error
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
32
|
+
const shikiModule = await getShiki();
|
|
33
|
+
return initializeHighlighter(shikiState, shikiModule);
|
|
157
34
|
}
|
|
158
35
|
|
|
159
|
-
// Get the mapped language or fallback to the original
|
|
160
|
-
function getMappedLanguage(language: string): BundledLanguage {
|
|
161
|
-
const mapped =
|
|
162
|
-
LANGUAGE_MAP[language.toLowerCase()] || language.toLowerCase();
|
|
163
|
-
return mapped as BundledLanguage;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Highlight code with Shiki
|
|
167
36
|
export async function highlightCode(
|
|
168
37
|
code: string,
|
|
169
38
|
language: string,
|
|
@@ -171,39 +40,20 @@ export async function highlightCode(
|
|
|
171
40
|
): Promise<string> {
|
|
172
41
|
try {
|
|
173
42
|
const highlighter = await initializeShiki();
|
|
174
|
-
let mappedLanguage = getMappedLanguage(language);
|
|
175
|
-
|
|
176
|
-
// Try to load the language asynchronously if it's not already loaded
|
|
177
|
-
await loadLanguageIfNeeded(highlighter, mappedLanguage);
|
|
178
|
-
|
|
179
|
-
// Check if the language is supported after potential async loading
|
|
180
|
-
const loadedLanguages = highlighter.getLoadedLanguages();
|
|
181
|
-
if (!loadedLanguages.includes(mappedLanguage)) {
|
|
182
|
-
mappedLanguage = "text" as BundledLanguage;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
43
|
const { transformerColorizedBrackets } = await getBrackets();
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
theme
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
});
|
|
44
|
+
return highlightCodeWithShiki(
|
|
45
|
+
code,
|
|
46
|
+
language,
|
|
47
|
+
theme,
|
|
48
|
+
highlighter,
|
|
49
|
+
transformerColorizedBrackets
|
|
50
|
+
);
|
|
194
51
|
} catch (error) {
|
|
195
52
|
console.error("Failed to highlight code with Shiki:", error);
|
|
196
|
-
|
|
197
|
-
return `<pre class="shiki ${theme}"><code>${escapeHtml(
|
|
198
|
-
code
|
|
199
|
-
)}</code></pre>`;
|
|
53
|
+
return `<pre class="shiki ${theme}"><code>${escapeHtml(code)}</code></pre>`;
|
|
200
54
|
}
|
|
201
55
|
}
|
|
202
56
|
|
|
203
|
-
// Utility function to escape HTML
|
|
204
57
|
export function escapeHtml(text: string): string {
|
|
205
|
-
|
|
206
|
-
div.textContent = text;
|
|
207
|
-
// eslint-disable-next-line @lwc/lwc/no-inner-html
|
|
208
|
-
return div.innerHTML;
|
|
58
|
+
return coreEscapeHtml(text);
|
|
209
59
|
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { BundledLanguage, BundledTheme, HighlighterCore } from "shiki";
|
|
2
|
+
import { getCustomLanguageGrammars } from "dxUtils/shikiGrammars";
|
|
3
|
+
|
|
4
|
+
export interface ShikiModule {
|
|
5
|
+
createHighlighter: (options: {
|
|
6
|
+
themes: string[];
|
|
7
|
+
langs: BundledLanguage[];
|
|
8
|
+
}) => Promise<HighlighterCore>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface BracketsModule {
|
|
12
|
+
transformerColorizedBrackets: () => any;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ShikiState {
|
|
16
|
+
highlighter: HighlighterCore | null;
|
|
17
|
+
initialized: boolean;
|
|
18
|
+
initPromise: Promise<HighlighterCore> | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const THEME_MAP: Record<string, BundledTheme> = {
|
|
22
|
+
light: "light-plus",
|
|
23
|
+
dark: "material-theme-darker"
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const THEME_MAP_COLOR_REPLACEMENTS: Record<
|
|
27
|
+
string,
|
|
28
|
+
{ colorReplacements: Record<string, string> }
|
|
29
|
+
> = {
|
|
30
|
+
light: {
|
|
31
|
+
colorReplacements: {}
|
|
32
|
+
},
|
|
33
|
+
dark: {
|
|
34
|
+
colorReplacements: {
|
|
35
|
+
"#545454": "#8A8A8A"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const LANGUAGE_MAP: Record<string, BundledLanguage> = {
|
|
41
|
+
ssjs: "javascript",
|
|
42
|
+
gtl: "handlebars",
|
|
43
|
+
lwc: "jsx",
|
|
44
|
+
sql_docs_template: "sql",
|
|
45
|
+
visualforce: "html",
|
|
46
|
+
js: "javascript",
|
|
47
|
+
ts: "typescript",
|
|
48
|
+
yml: "yaml",
|
|
49
|
+
md: "markdown",
|
|
50
|
+
sh: "bash"
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const CORE_LANGUAGES: BundledLanguage[] = [
|
|
54
|
+
"apex",
|
|
55
|
+
"javascript",
|
|
56
|
+
"html",
|
|
57
|
+
"css",
|
|
58
|
+
"json",
|
|
59
|
+
"sql",
|
|
60
|
+
"bash",
|
|
61
|
+
"xml",
|
|
62
|
+
"graphql",
|
|
63
|
+
"jsx",
|
|
64
|
+
getCustomLanguageGrammars().ampscript
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
export const OPTIONAL_LANGUAGES: Record<string, any> = {
|
|
68
|
+
// @ts-ignore
|
|
69
|
+
typescript: "typescript",
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
markdown: "markdown",
|
|
72
|
+
// @ts-ignore
|
|
73
|
+
python: "python",
|
|
74
|
+
// @ts-ignore
|
|
75
|
+
java: "java",
|
|
76
|
+
// @ts-ignore
|
|
77
|
+
yaml: "yaml",
|
|
78
|
+
// @ts-ignore
|
|
79
|
+
php: "php",
|
|
80
|
+
// @ts-ignore
|
|
81
|
+
swift: "swift",
|
|
82
|
+
// @ts-ignore
|
|
83
|
+
kotlin: "kotlin",
|
|
84
|
+
// @ts-ignore
|
|
85
|
+
handlebars: "handlebars",
|
|
86
|
+
// @ts-ignore
|
|
87
|
+
dataweave: getCustomLanguageGrammars().dataweave,
|
|
88
|
+
// @ts-ignore
|
|
89
|
+
agentscript: getCustomLanguageGrammars().agentscript
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export async function loadLanguageIfNeeded(
|
|
93
|
+
highlighter: HighlighterCore,
|
|
94
|
+
language: string
|
|
95
|
+
): Promise<void> {
|
|
96
|
+
const loadedLanguages = highlighter.getLoadedLanguages();
|
|
97
|
+
|
|
98
|
+
if (!loadedLanguages.includes(language as BundledLanguage)) {
|
|
99
|
+
const languageLoader = OPTIONAL_LANGUAGES[language];
|
|
100
|
+
|
|
101
|
+
if (languageLoader) {
|
|
102
|
+
try {
|
|
103
|
+
await highlighter.loadLanguage(languageLoader);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.warn(
|
|
106
|
+
`Failed to load optional language ${language}:`,
|
|
107
|
+
error
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function getMappedLanguage(language: string): BundledLanguage {
|
|
115
|
+
const mapped =
|
|
116
|
+
LANGUAGE_MAP[language.toLowerCase()] || language.toLowerCase();
|
|
117
|
+
return mapped as BundledLanguage;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function escapeHtml(text: string): string {
|
|
121
|
+
const div = document.createElement("div");
|
|
122
|
+
div.textContent = text;
|
|
123
|
+
// eslint-disable-next-line @lwc/lwc/no-inner-html
|
|
124
|
+
return div.innerHTML;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function createShikiState(): ShikiState {
|
|
128
|
+
return {
|
|
129
|
+
highlighter: null,
|
|
130
|
+
initialized: false,
|
|
131
|
+
initPromise: null
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export async function initializeHighlighter(
|
|
136
|
+
shikiState: ShikiState,
|
|
137
|
+
shikiModule: ShikiModule
|
|
138
|
+
): Promise<HighlighterCore> {
|
|
139
|
+
if (shikiState.highlighter) {
|
|
140
|
+
return shikiState.highlighter;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (shikiState.initPromise) {
|
|
144
|
+
return shikiState.initPromise;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
shikiState.initPromise = (async () => {
|
|
148
|
+
const highlighter = await shikiModule.createHighlighter({
|
|
149
|
+
themes: ["light-plus", "material-theme-darker"],
|
|
150
|
+
langs: CORE_LANGUAGES
|
|
151
|
+
});
|
|
152
|
+
shikiState.highlighter = highlighter;
|
|
153
|
+
shikiState.initialized = true;
|
|
154
|
+
return highlighter;
|
|
155
|
+
})();
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
return await shikiState.initPromise;
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.error("Failed to initialize Shiki:", error);
|
|
161
|
+
shikiState.initPromise = null;
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export async function highlightCodeWithShiki(
|
|
167
|
+
code: string,
|
|
168
|
+
language: string,
|
|
169
|
+
theme: "light" | "dark",
|
|
170
|
+
highlighter: HighlighterCore,
|
|
171
|
+
transformerColorizedBrackets: () => any
|
|
172
|
+
): Promise<string> {
|
|
173
|
+
let mappedLanguage = getMappedLanguage(language);
|
|
174
|
+
|
|
175
|
+
await loadLanguageIfNeeded(highlighter, mappedLanguage);
|
|
176
|
+
|
|
177
|
+
const loadedLanguages = highlighter.getLoadedLanguages();
|
|
178
|
+
if (!loadedLanguages.includes(mappedLanguage)) {
|
|
179
|
+
mappedLanguage = "text" as BundledLanguage;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return highlighter.codeToHtml(code, {
|
|
183
|
+
lang: mappedLanguage,
|
|
184
|
+
theme: THEME_MAP[theme],
|
|
185
|
+
transformers: [transformerColorizedBrackets()],
|
|
186
|
+
colorReplacements: THEME_MAP_COLOR_REPLACEMENTS[theme].colorReplacements
|
|
187
|
+
});
|
|
188
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { HighlighterCore } from "shiki";
|
|
2
|
+
import * as shikiModule from "shiki";
|
|
3
|
+
import { transformerColorizedBrackets } from "@shikijs/colorized-brackets";
|
|
4
|
+
import {
|
|
5
|
+
createShikiState,
|
|
6
|
+
initializeHighlighter,
|
|
7
|
+
highlightCodeWithShiki,
|
|
8
|
+
escapeHtml as coreEscapeHtml,
|
|
9
|
+
ShikiState
|
|
10
|
+
} from "dxUtils/shikiCore";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Static loading version of Shiki.
|
|
14
|
+
* Uses static imports - shiki is bundled with this module.
|
|
15
|
+
* Use this for SSG compatibility and it is very specific to SSG generated components using LWR.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const shikiState: ShikiState = createShikiState();
|
|
19
|
+
|
|
20
|
+
async function initializeShiki(): Promise<HighlighterCore> {
|
|
21
|
+
return initializeHighlighter(shikiState, shikiModule);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function highlightCode(
|
|
25
|
+
code: string,
|
|
26
|
+
language: string,
|
|
27
|
+
theme: "light" | "dark" = "light"
|
|
28
|
+
): Promise<string> {
|
|
29
|
+
try {
|
|
30
|
+
const highlighter = await initializeShiki();
|
|
31
|
+
return highlightCodeWithShiki(
|
|
32
|
+
code,
|
|
33
|
+
language,
|
|
34
|
+
theme,
|
|
35
|
+
highlighter,
|
|
36
|
+
transformerColorizedBrackets
|
|
37
|
+
);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error("Failed to highlight code with Shiki:", error);
|
|
40
|
+
return `<pre class="shiki ${theme}"><code>${escapeHtml(code)}</code></pre>`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function escapeHtml(text: string): string {
|
|
45
|
+
return coreEscapeHtml(text);
|
|
46
|
+
}
|